blob: 87a370727ed5ce9cebeb8750c87c6e0047debfda [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),
Francois Romieuf23e7fd2007-10-04 22:36:14 +0200687};
688
Ivan Vecera355423d2009-02-06 21:49:57 -0800689struct rtl8169_counters {
690 __le64 tx_packets;
691 __le64 rx_packets;
692 __le64 tx_errors;
693 __le32 rx_errors;
694 __le16 rx_missed;
695 __le16 align_errors;
696 __le32 tx_one_collision;
697 __le32 tx_multi_collision;
698 __le64 rx_unicast;
699 __le64 rx_broadcast;
700 __le32 rx_multicast;
701 __le16 tx_aborted;
702 __le16 tx_underun;
703};
704
Francois Romieuda78dbf2012-01-26 14:18:23 +0100705enum rtl_flag {
Francois Romieu6c4a70c2012-01-31 10:56:44 +0100706 RTL_FLAG_TASK_ENABLED,
Francois Romieuda78dbf2012-01-26 14:18:23 +0100707 RTL_FLAG_TASK_SLOW_PENDING,
708 RTL_FLAG_TASK_RESET_PENDING,
709 RTL_FLAG_TASK_PHY_PENDING,
710 RTL_FLAG_MAX
711};
712
Junchang Wang8027aa22012-03-04 23:30:32 +0100713struct rtl8169_stats {
714 u64 packets;
715 u64 bytes;
716 struct u64_stats_sync syncp;
717};
718
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719struct rtl8169_private {
720 void __iomem *mmio_addr; /* memory map physical address */
Francois Romieucecb5fd2011-04-01 10:21:07 +0200721 struct pci_dev *pci_dev;
David Howellsc4028952006-11-22 14:57:56 +0000722 struct net_device *dev;
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700723 struct napi_struct napi;
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +0200724 u32 msg_enable;
Francois Romieu2b7b4312011-04-18 22:53:24 -0700725 u16 txd_version;
726 u16 mac_version;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727 u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */
728 u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */
729 u32 dirty_rx;
730 u32 dirty_tx;
Junchang Wang8027aa22012-03-04 23:30:32 +0100731 struct rtl8169_stats rx_stats;
732 struct rtl8169_stats tx_stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733 struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */
734 struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */
735 dma_addr_t TxPhyAddr;
736 dma_addr_t RxPhyAddr;
Eric Dumazet6f0333b2010-10-11 11:17:47 +0000737 void *Rx_databuff[NUM_RX_DESC]; /* Rx data buffers */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738 struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739 struct timer_list timer;
740 u16 cp_cmd;
Francois Romieuda78dbf2012-01-26 14:18:23 +0100741
742 u16 event_slow;
françois romieuc0e45c12011-01-03 15:08:04 +0000743
744 struct mdio_ops {
Francois Romieu24192212012-07-06 20:19:42 +0200745 void (*write)(struct rtl8169_private *, int, int);
746 int (*read)(struct rtl8169_private *, int);
françois romieuc0e45c12011-01-03 15:08:04 +0000747 } mdio_ops;
748
françois romieu065c27c2011-01-03 15:08:12 +0000749 struct pll_power_ops {
750 void (*down)(struct rtl8169_private *);
751 void (*up)(struct rtl8169_private *);
752 } pll_power_ops;
753
Francois Romieud58d46b2011-05-03 16:38:29 +0200754 struct jumbo_ops {
755 void (*enable)(struct rtl8169_private *);
756 void (*disable)(struct rtl8169_private *);
757 } jumbo_ops;
758
Hayes Wangbeb1fe12012-03-30 14:33:01 +0800759 struct csi_ops {
Francois Romieu52989f02012-07-06 13:37:00 +0200760 void (*write)(struct rtl8169_private *, int, int);
761 u32 (*read)(struct rtl8169_private *, int);
Hayes Wangbeb1fe12012-03-30 14:33:01 +0800762 } csi_ops;
763
Oliver Neukum54405cd2011-01-06 21:55:13 +0100764 int (*set_speed)(struct net_device *, u8 aneg, u16 sp, u8 dpx, u32 adv);
Francois Romieuccdffb92008-07-26 14:26:06 +0200765 int (*get_settings)(struct net_device *, struct ethtool_cmd *);
françois romieu4da19632011-01-03 15:07:55 +0000766 void (*phy_reset_enable)(struct rtl8169_private *tp);
Francois Romieu07ce4062007-02-23 23:36:39 +0100767 void (*hw_start)(struct net_device *);
françois romieu4da19632011-01-03 15:07:55 +0000768 unsigned int (*phy_reset_pending)(struct rtl8169_private *tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769 unsigned int (*link_ok)(void __iomem *);
Francois Romieu8b4ab282008-11-19 22:05:25 -0800770 int (*do_ioctl)(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd);
Francois Romieu4422bcd2012-01-26 11:23:32 +0100771
772 struct {
Francois Romieuda78dbf2012-01-26 14:18:23 +0100773 DECLARE_BITMAP(flags, RTL_FLAG_MAX);
774 struct mutex mutex;
Francois Romieu4422bcd2012-01-26 11:23:32 +0100775 struct work_struct work;
776 } wk;
777
Francois Romieuf23e7fd2007-10-04 22:36:14 +0200778 unsigned features;
Francois Romieuccdffb92008-07-26 14:26:06 +0200779
780 struct mii_if_info mii;
Ivan Vecera355423d2009-02-06 21:49:57 -0800781 struct rtl8169_counters counters;
Rafael J. Wysockie1759442010-03-14 14:33:51 +0000782 u32 saved_wolopts;
David S. Miller8decf862011-09-22 03:23:13 -0400783 u32 opts1_mask;
françois romieuf1e02ed2011-01-13 13:07:53 +0000784
Francois Romieub6ffd972011-06-17 17:00:05 +0200785 struct rtl_fw {
786 const struct firmware *fw;
Francois Romieu1c361ef2011-06-17 17:16:24 +0200787
788#define RTL_VER_SIZE 32
789
790 char version[RTL_VER_SIZE];
791
792 struct rtl_fw_phy_action {
793 __le32 *code;
794 size_t size;
795 } phy_action;
Francois Romieub6ffd972011-06-17 17:00:05 +0200796 } *rtl_fw;
Phil Carmody497888c2011-07-14 15:07:13 +0300797#define RTL_FIRMWARE_UNKNOWN ERR_PTR(-EAGAIN)
Hayes Wangc5583862012-07-02 17:23:22 +0800798
799 u32 ocp_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800};
801
Ralf Baechle979b6c12005-06-13 14:30:40 -0700802MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804module_param(use_dac, int, 0);
David S. Miller4300e8c2010-03-26 10:23:30 -0700805MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot.");
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +0200806module_param_named(debug, debug.msg_enable, int, 0);
807MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808MODULE_LICENSE("GPL");
809MODULE_VERSION(RTL8169_VERSION);
françois romieubca03d52011-01-03 15:07:31 +0000810MODULE_FIRMWARE(FIRMWARE_8168D_1);
811MODULE_FIRMWARE(FIRMWARE_8168D_2);
hayeswang01dc7fe2011-03-21 01:50:28 +0000812MODULE_FIRMWARE(FIRMWARE_8168E_1);
813MODULE_FIRMWARE(FIRMWARE_8168E_2);
David S. Miller8decf862011-09-22 03:23:13 -0400814MODULE_FIRMWARE(FIRMWARE_8168E_3);
Hayes Wang5a5e4442011-02-22 17:26:21 +0800815MODULE_FIRMWARE(FIRMWARE_8105E_1);
Hayes Wangc2218922011-09-06 16:55:18 +0800816MODULE_FIRMWARE(FIRMWARE_8168F_1);
817MODULE_FIRMWARE(FIRMWARE_8168F_2);
Hayes Wang7e18dca2012-03-30 14:33:02 +0800818MODULE_FIRMWARE(FIRMWARE_8402_1);
Hayes Wangb3d7b2f2012-03-30 14:48:06 +0800819MODULE_FIRMWARE(FIRMWARE_8411_1);
Hayes Wang5598bfe2012-07-02 17:23:21 +0800820MODULE_FIRMWARE(FIRMWARE_8106E_1);
Hayes Wangc5583862012-07-02 17:23:22 +0800821MODULE_FIRMWARE(FIRMWARE_8168G_1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822
Francois Romieuda78dbf2012-01-26 14:18:23 +0100823static void rtl_lock_work(struct rtl8169_private *tp)
824{
825 mutex_lock(&tp->wk.mutex);
826}
827
828static void rtl_unlock_work(struct rtl8169_private *tp)
829{
830 mutex_unlock(&tp->wk.mutex);
831}
832
Francois Romieud58d46b2011-05-03 16:38:29 +0200833static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force)
834{
Jiang Liu7d7903b2012-07-24 17:20:16 +0800835 pcie_capability_clear_and_set_word(pdev, PCI_EXP_DEVCTL,
836 PCI_EXP_DEVCTL_READRQ, force);
Francois Romieud58d46b2011-05-03 16:38:29 +0200837}
838
Francois Romieuffc46952012-07-06 14:19:23 +0200839struct rtl_cond {
840 bool (*check)(struct rtl8169_private *);
841 const char *msg;
842};
843
844static void rtl_udelay(unsigned int d)
845{
846 udelay(d);
847}
848
849static bool rtl_loop_wait(struct rtl8169_private *tp, const struct rtl_cond *c,
850 void (*delay)(unsigned int), unsigned int d, int n,
851 bool high)
852{
853 int i;
854
855 for (i = 0; i < n; i++) {
856 delay(d);
857 if (c->check(tp) == high)
858 return true;
859 }
Francois Romieu82e316e2012-07-11 23:39:51 +0200860 netif_err(tp, drv, tp->dev, "%s == %d (loop: %d, delay: %d).\n",
861 c->msg, !high, n, d);
Francois Romieuffc46952012-07-06 14:19:23 +0200862 return false;
863}
864
865static bool rtl_udelay_loop_wait_high(struct rtl8169_private *tp,
866 const struct rtl_cond *c,
867 unsigned int d, int n)
868{
869 return rtl_loop_wait(tp, c, rtl_udelay, d, n, true);
870}
871
872static bool rtl_udelay_loop_wait_low(struct rtl8169_private *tp,
873 const struct rtl_cond *c,
874 unsigned int d, int n)
875{
876 return rtl_loop_wait(tp, c, rtl_udelay, d, n, false);
877}
878
879static bool rtl_msleep_loop_wait_high(struct rtl8169_private *tp,
880 const struct rtl_cond *c,
881 unsigned int d, int n)
882{
883 return rtl_loop_wait(tp, c, msleep, d, n, true);
884}
885
886static bool rtl_msleep_loop_wait_low(struct rtl8169_private *tp,
887 const struct rtl_cond *c,
888 unsigned int d, int n)
889{
890 return rtl_loop_wait(tp, c, msleep, d, n, false);
891}
892
893#define DECLARE_RTL_COND(name) \
894static bool name ## _check(struct rtl8169_private *); \
895 \
896static const struct rtl_cond name = { \
897 .check = name ## _check, \
898 .msg = #name \
899}; \
900 \
901static bool name ## _check(struct rtl8169_private *tp)
902
903DECLARE_RTL_COND(rtl_ocpar_cond)
904{
905 void __iomem *ioaddr = tp->mmio_addr;
906
907 return RTL_R32(OCPAR) & OCPAR_FLAG;
908}
909
françois romieub646d902011-01-03 15:08:21 +0000910static u32 ocp_read(struct rtl8169_private *tp, u8 mask, u16 reg)
911{
912 void __iomem *ioaddr = tp->mmio_addr;
françois romieub646d902011-01-03 15:08:21 +0000913
914 RTL_W32(OCPAR, ((u32)mask & 0x0f) << 12 | (reg & 0x0fff));
Francois Romieuffc46952012-07-06 14:19:23 +0200915
916 return rtl_udelay_loop_wait_high(tp, &rtl_ocpar_cond, 100, 20) ?
917 RTL_R32(OCPDR) : ~0;
françois romieub646d902011-01-03 15:08:21 +0000918}
919
920static void ocp_write(struct rtl8169_private *tp, u8 mask, u16 reg, u32 data)
921{
922 void __iomem *ioaddr = tp->mmio_addr;
françois romieub646d902011-01-03 15:08:21 +0000923
924 RTL_W32(OCPDR, data);
925 RTL_W32(OCPAR, OCPAR_FLAG | ((u32)mask & 0x0f) << 12 | (reg & 0x0fff));
Francois Romieuffc46952012-07-06 14:19:23 +0200926
927 rtl_udelay_loop_wait_low(tp, &rtl_ocpar_cond, 100, 20);
928}
929
930DECLARE_RTL_COND(rtl_eriar_cond)
931{
932 void __iomem *ioaddr = tp->mmio_addr;
933
934 return RTL_R32(ERIAR) & ERIAR_FLAG;
françois romieub646d902011-01-03 15:08:21 +0000935}
936
Hayes Wangfac5b3c2011-02-22 17:26:20 +0800937static void rtl8168_oob_notify(struct rtl8169_private *tp, u8 cmd)
françois romieub646d902011-01-03 15:08:21 +0000938{
Hayes Wangfac5b3c2011-02-22 17:26:20 +0800939 void __iomem *ioaddr = tp->mmio_addr;
françois romieub646d902011-01-03 15:08:21 +0000940
941 RTL_W8(ERIDR, cmd);
942 RTL_W32(ERIAR, 0x800010e8);
943 msleep(2);
Francois Romieuffc46952012-07-06 14:19:23 +0200944
945 if (!rtl_udelay_loop_wait_low(tp, &rtl_eriar_cond, 100, 5))
946 return;
françois romieub646d902011-01-03 15:08:21 +0000947
Hayes Wangfac5b3c2011-02-22 17:26:20 +0800948 ocp_write(tp, 0x1, 0x30, 0x00000001);
françois romieub646d902011-01-03 15:08:21 +0000949}
950
951#define OOB_CMD_RESET 0x00
952#define OOB_CMD_DRIVER_START 0x05
953#define OOB_CMD_DRIVER_STOP 0x06
954
Francois Romieucecb5fd2011-04-01 10:21:07 +0200955static u16 rtl8168_get_ocp_reg(struct rtl8169_private *tp)
956{
957 return (tp->mac_version == RTL_GIGA_MAC_VER_31) ? 0xb8 : 0x10;
958}
959
Francois Romieuffc46952012-07-06 14:19:23 +0200960DECLARE_RTL_COND(rtl_ocp_read_cond)
françois romieub646d902011-01-03 15:08:21 +0000961{
Francois Romieucecb5fd2011-04-01 10:21:07 +0200962 u16 reg;
françois romieub646d902011-01-03 15:08:21 +0000963
Francois Romieucecb5fd2011-04-01 10:21:07 +0200964 reg = rtl8168_get_ocp_reg(tp);
hayeswang4804b3b2011-03-21 01:50:29 +0000965
Francois Romieuffc46952012-07-06 14:19:23 +0200966 return ocp_read(tp, 0x0f, reg) & 0x00000800;
967}
968
969static void rtl8168_driver_start(struct rtl8169_private *tp)
970{
971 rtl8168_oob_notify(tp, OOB_CMD_DRIVER_START);
972
973 rtl_msleep_loop_wait_high(tp, &rtl_ocp_read_cond, 10, 10);
françois romieub646d902011-01-03 15:08:21 +0000974}
975
976static void rtl8168_driver_stop(struct rtl8169_private *tp)
977{
françois romieub646d902011-01-03 15:08:21 +0000978 rtl8168_oob_notify(tp, OOB_CMD_DRIVER_STOP);
979
Francois Romieuffc46952012-07-06 14:19:23 +0200980 rtl_msleep_loop_wait_low(tp, &rtl_ocp_read_cond, 10, 10);
françois romieub646d902011-01-03 15:08:21 +0000981}
982
hayeswang4804b3b2011-03-21 01:50:29 +0000983static int r8168dp_check_dash(struct rtl8169_private *tp)
984{
Francois Romieucecb5fd2011-04-01 10:21:07 +0200985 u16 reg = rtl8168_get_ocp_reg(tp);
hayeswang4804b3b2011-03-21 01:50:29 +0000986
Francois Romieucecb5fd2011-04-01 10:21:07 +0200987 return (ocp_read(tp, 0x0f, reg) & 0x00008000) ? 1 : 0;
hayeswang4804b3b2011-03-21 01:50:29 +0000988}
françois romieub646d902011-01-03 15:08:21 +0000989
Hayes Wangc5583862012-07-02 17:23:22 +0800990static bool rtl_ocp_reg_failure(struct rtl8169_private *tp, u32 reg)
991{
992 if (reg & 0xffff0001) {
993 netif_err(tp, drv, tp->dev, "Invalid ocp reg %x!\n", reg);
994 return true;
995 }
996 return false;
997}
998
999DECLARE_RTL_COND(rtl_ocp_gphy_cond)
1000{
1001 void __iomem *ioaddr = tp->mmio_addr;
1002
1003 return RTL_R32(GPHY_OCP) & OCPAR_FLAG;
1004}
1005
1006static void r8168_phy_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)
1007{
1008 void __iomem *ioaddr = tp->mmio_addr;
1009
1010 if (rtl_ocp_reg_failure(tp, reg))
1011 return;
1012
1013 RTL_W32(GPHY_OCP, OCPAR_FLAG | (reg << 15) | data);
1014
1015 rtl_udelay_loop_wait_low(tp, &rtl_ocp_gphy_cond, 25, 10);
1016}
1017
1018static u16 r8168_phy_ocp_read(struct rtl8169_private *tp, u32 reg)
1019{
1020 void __iomem *ioaddr = tp->mmio_addr;
1021
1022 if (rtl_ocp_reg_failure(tp, reg))
1023 return 0;
1024
1025 RTL_W32(GPHY_OCP, reg << 15);
1026
1027 return rtl_udelay_loop_wait_high(tp, &rtl_ocp_gphy_cond, 25, 10) ?
1028 (RTL_R32(GPHY_OCP) & 0xffff) : ~0;
1029}
1030
1031static void rtl_w1w0_phy_ocp(struct rtl8169_private *tp, int reg, int p, int m)
1032{
1033 int val;
1034
1035 val = r8168_phy_ocp_read(tp, reg);
1036 r8168_phy_ocp_write(tp, reg, (val | p) & ~m);
1037}
1038
Hayes Wangc5583862012-07-02 17:23:22 +08001039static void r8168_mac_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)
1040{
1041 void __iomem *ioaddr = tp->mmio_addr;
1042
1043 if (rtl_ocp_reg_failure(tp, reg))
1044 return;
1045
1046 RTL_W32(OCPDR, OCPAR_FLAG | (reg << 15) | data);
Hayes Wangc5583862012-07-02 17:23:22 +08001047}
1048
1049static u16 r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg)
1050{
1051 void __iomem *ioaddr = tp->mmio_addr;
1052
1053 if (rtl_ocp_reg_failure(tp, reg))
1054 return 0;
1055
1056 RTL_W32(OCPDR, reg << 15);
1057
Hayes Wang3a83ad12012-07-11 20:31:56 +08001058 return RTL_R32(OCPDR);
Hayes Wangc5583862012-07-02 17:23:22 +08001059}
1060
1061#define OCP_STD_PHY_BASE 0xa400
1062
1063static void r8168g_mdio_write(struct rtl8169_private *tp, int reg, int value)
1064{
1065 if (reg == 0x1f) {
1066 tp->ocp_base = value ? value << 4 : OCP_STD_PHY_BASE;
1067 return;
1068 }
1069
1070 if (tp->ocp_base != OCP_STD_PHY_BASE)
1071 reg -= 0x10;
1072
1073 r8168_phy_ocp_write(tp, tp->ocp_base + reg * 2, value);
1074}
1075
1076static int r8168g_mdio_read(struct rtl8169_private *tp, int reg)
1077{
1078 if (tp->ocp_base != OCP_STD_PHY_BASE)
1079 reg -= 0x10;
1080
1081 return r8168_phy_ocp_read(tp, tp->ocp_base + reg * 2);
1082}
1083
Francois Romieuffc46952012-07-06 14:19:23 +02001084DECLARE_RTL_COND(rtl_phyar_cond)
1085{
1086 void __iomem *ioaddr = tp->mmio_addr;
1087
1088 return RTL_R32(PHYAR) & 0x80000000;
1089}
1090
Francois Romieu24192212012-07-06 20:19:42 +02001091static void r8169_mdio_write(struct rtl8169_private *tp, int reg, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092{
Francois Romieu24192212012-07-06 20:19:42 +02001093 void __iomem *ioaddr = tp->mmio_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094
Francois Romieu24192212012-07-06 20:19:42 +02001095 RTL_W32(PHYAR, 0x80000000 | (reg & 0x1f) << 16 | (value & 0xffff));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096
Francois Romieuffc46952012-07-06 14:19:23 +02001097 rtl_udelay_loop_wait_low(tp, &rtl_phyar_cond, 25, 20);
Timo Teräs024a07b2010-06-06 15:38:47 -07001098 /*
Timo Teräs81a95f02010-06-09 17:31:48 -07001099 * According to hardware specs a 20us delay is required after write
1100 * complete indication, but before sending next command.
Timo Teräs024a07b2010-06-06 15:38:47 -07001101 */
Timo Teräs81a95f02010-06-09 17:31:48 -07001102 udelay(20);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103}
1104
Francois Romieu24192212012-07-06 20:19:42 +02001105static int r8169_mdio_read(struct rtl8169_private *tp, int reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106{
Francois Romieu24192212012-07-06 20:19:42 +02001107 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieuffc46952012-07-06 14:19:23 +02001108 int value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109
Francois Romieu24192212012-07-06 20:19:42 +02001110 RTL_W32(PHYAR, 0x0 | (reg & 0x1f) << 16);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111
Francois Romieuffc46952012-07-06 14:19:23 +02001112 value = rtl_udelay_loop_wait_high(tp, &rtl_phyar_cond, 25, 20) ?
1113 RTL_R32(PHYAR) & 0xffff : ~0;
1114
Timo Teräs81a95f02010-06-09 17:31:48 -07001115 /*
1116 * According to hardware specs a 20us delay is required after read
1117 * complete indication, but before sending next command.
1118 */
1119 udelay(20);
1120
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121 return value;
1122}
1123
Francois Romieu24192212012-07-06 20:19:42 +02001124static void r8168dp_1_mdio_access(struct rtl8169_private *tp, int reg, u32 data)
françois romieuc0e45c12011-01-03 15:08:04 +00001125{
Francois Romieu24192212012-07-06 20:19:42 +02001126 void __iomem *ioaddr = tp->mmio_addr;
françois romieuc0e45c12011-01-03 15:08:04 +00001127
Francois Romieu24192212012-07-06 20:19:42 +02001128 RTL_W32(OCPDR, data | ((reg & OCPDR_REG_MASK) << OCPDR_GPHY_REG_SHIFT));
françois romieuc0e45c12011-01-03 15:08:04 +00001129 RTL_W32(OCPAR, OCPAR_GPHY_WRITE_CMD);
1130 RTL_W32(EPHY_RXER_NUM, 0);
1131
Francois Romieuffc46952012-07-06 14:19:23 +02001132 rtl_udelay_loop_wait_low(tp, &rtl_ocpar_cond, 1000, 100);
françois romieuc0e45c12011-01-03 15:08:04 +00001133}
1134
Francois Romieu24192212012-07-06 20:19:42 +02001135static void r8168dp_1_mdio_write(struct rtl8169_private *tp, int reg, int value)
françois romieuc0e45c12011-01-03 15:08:04 +00001136{
Francois Romieu24192212012-07-06 20:19:42 +02001137 r8168dp_1_mdio_access(tp, reg,
1138 OCPDR_WRITE_CMD | (value & OCPDR_DATA_MASK));
françois romieuc0e45c12011-01-03 15:08:04 +00001139}
1140
Francois Romieu24192212012-07-06 20:19:42 +02001141static int r8168dp_1_mdio_read(struct rtl8169_private *tp, int reg)
françois romieuc0e45c12011-01-03 15:08:04 +00001142{
Francois Romieu24192212012-07-06 20:19:42 +02001143 void __iomem *ioaddr = tp->mmio_addr;
françois romieuc0e45c12011-01-03 15:08:04 +00001144
Francois Romieu24192212012-07-06 20:19:42 +02001145 r8168dp_1_mdio_access(tp, reg, OCPDR_READ_CMD);
françois romieuc0e45c12011-01-03 15:08:04 +00001146
1147 mdelay(1);
1148 RTL_W32(OCPAR, OCPAR_GPHY_READ_CMD);
1149 RTL_W32(EPHY_RXER_NUM, 0);
1150
Francois Romieuffc46952012-07-06 14:19:23 +02001151 return rtl_udelay_loop_wait_high(tp, &rtl_ocpar_cond, 1000, 100) ?
1152 RTL_R32(OCPDR) & OCPDR_DATA_MASK : ~0;
françois romieuc0e45c12011-01-03 15:08:04 +00001153}
1154
françois romieue6de30d2011-01-03 15:08:37 +00001155#define R8168DP_1_MDIO_ACCESS_BIT 0x00020000
1156
1157static void r8168dp_2_mdio_start(void __iomem *ioaddr)
1158{
1159 RTL_W32(0xd0, RTL_R32(0xd0) & ~R8168DP_1_MDIO_ACCESS_BIT);
1160}
1161
1162static void r8168dp_2_mdio_stop(void __iomem *ioaddr)
1163{
1164 RTL_W32(0xd0, RTL_R32(0xd0) | R8168DP_1_MDIO_ACCESS_BIT);
1165}
1166
Francois Romieu24192212012-07-06 20:19:42 +02001167static void r8168dp_2_mdio_write(struct rtl8169_private *tp, int reg, int value)
françois romieue6de30d2011-01-03 15:08:37 +00001168{
Francois Romieu24192212012-07-06 20:19:42 +02001169 void __iomem *ioaddr = tp->mmio_addr;
1170
françois romieue6de30d2011-01-03 15:08:37 +00001171 r8168dp_2_mdio_start(ioaddr);
1172
Francois Romieu24192212012-07-06 20:19:42 +02001173 r8169_mdio_write(tp, reg, value);
françois romieue6de30d2011-01-03 15:08:37 +00001174
1175 r8168dp_2_mdio_stop(ioaddr);
1176}
1177
Francois Romieu24192212012-07-06 20:19:42 +02001178static int r8168dp_2_mdio_read(struct rtl8169_private *tp, int reg)
françois romieue6de30d2011-01-03 15:08:37 +00001179{
Francois Romieu24192212012-07-06 20:19:42 +02001180 void __iomem *ioaddr = tp->mmio_addr;
françois romieue6de30d2011-01-03 15:08:37 +00001181 int value;
1182
1183 r8168dp_2_mdio_start(ioaddr);
1184
Francois Romieu24192212012-07-06 20:19:42 +02001185 value = r8169_mdio_read(tp, reg);
françois romieue6de30d2011-01-03 15:08:37 +00001186
1187 r8168dp_2_mdio_stop(ioaddr);
1188
1189 return value;
1190}
1191
françois romieu4da19632011-01-03 15:07:55 +00001192static void rtl_writephy(struct rtl8169_private *tp, int location, u32 val)
Francois Romieudacf8152008-08-02 20:44:13 +02001193{
Francois Romieu24192212012-07-06 20:19:42 +02001194 tp->mdio_ops.write(tp, location, val);
Francois Romieudacf8152008-08-02 20:44:13 +02001195}
1196
françois romieu4da19632011-01-03 15:07:55 +00001197static int rtl_readphy(struct rtl8169_private *tp, int location)
1198{
Francois Romieu24192212012-07-06 20:19:42 +02001199 return tp->mdio_ops.read(tp, location);
françois romieu4da19632011-01-03 15:07:55 +00001200}
1201
1202static void rtl_patchphy(struct rtl8169_private *tp, int reg_addr, int value)
1203{
1204 rtl_writephy(tp, reg_addr, rtl_readphy(tp, reg_addr) | value);
1205}
1206
1207static void rtl_w1w0_phy(struct rtl8169_private *tp, int reg_addr, int p, int m)
françois romieudaf9df62009-10-07 12:44:20 +00001208{
1209 int val;
1210
françois romieu4da19632011-01-03 15:07:55 +00001211 val = rtl_readphy(tp, reg_addr);
1212 rtl_writephy(tp, reg_addr, (val | p) & ~m);
françois romieudaf9df62009-10-07 12:44:20 +00001213}
1214
Francois Romieuccdffb92008-07-26 14:26:06 +02001215static void rtl_mdio_write(struct net_device *dev, int phy_id, int location,
1216 int val)
1217{
1218 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieuccdffb92008-07-26 14:26:06 +02001219
françois romieu4da19632011-01-03 15:07:55 +00001220 rtl_writephy(tp, location, val);
Francois Romieuccdffb92008-07-26 14:26:06 +02001221}
1222
1223static int rtl_mdio_read(struct net_device *dev, int phy_id, int location)
1224{
1225 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieuccdffb92008-07-26 14:26:06 +02001226
françois romieu4da19632011-01-03 15:07:55 +00001227 return rtl_readphy(tp, location);
Francois Romieuccdffb92008-07-26 14:26:06 +02001228}
1229
Francois Romieuffc46952012-07-06 14:19:23 +02001230DECLARE_RTL_COND(rtl_ephyar_cond)
1231{
1232 void __iomem *ioaddr = tp->mmio_addr;
1233
1234 return RTL_R32(EPHYAR) & EPHYAR_FLAG;
1235}
1236
Francois Romieufdf6fc02012-07-06 22:40:38 +02001237static void rtl_ephy_write(struct rtl8169_private *tp, int reg_addr, int value)
Francois Romieudacf8152008-08-02 20:44:13 +02001238{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001239 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieudacf8152008-08-02 20:44:13 +02001240
1241 RTL_W32(EPHYAR, EPHYAR_WRITE_CMD | (value & EPHYAR_DATA_MASK) |
1242 (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT);
1243
Francois Romieuffc46952012-07-06 14:19:23 +02001244 rtl_udelay_loop_wait_low(tp, &rtl_ephyar_cond, 10, 100);
1245
1246 udelay(10);
Francois Romieudacf8152008-08-02 20:44:13 +02001247}
1248
Francois Romieufdf6fc02012-07-06 22:40:38 +02001249static u16 rtl_ephy_read(struct rtl8169_private *tp, int reg_addr)
Francois Romieudacf8152008-08-02 20:44:13 +02001250{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001251 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieudacf8152008-08-02 20:44:13 +02001252
1253 RTL_W32(EPHYAR, (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT);
1254
Francois Romieuffc46952012-07-06 14:19:23 +02001255 return rtl_udelay_loop_wait_high(tp, &rtl_ephyar_cond, 10, 100) ?
1256 RTL_R32(EPHYAR) & EPHYAR_DATA_MASK : ~0;
Francois Romieudacf8152008-08-02 20:44:13 +02001257}
1258
Francois Romieufdf6fc02012-07-06 22:40:38 +02001259static void rtl_eri_write(struct rtl8169_private *tp, int addr, u32 mask,
1260 u32 val, int type)
Hayes Wang133ac402011-07-06 15:58:05 +08001261{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001262 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang133ac402011-07-06 15:58:05 +08001263
1264 BUG_ON((addr & 3) || (mask == 0));
1265 RTL_W32(ERIDR, val);
1266 RTL_W32(ERIAR, ERIAR_WRITE_CMD | type | mask | addr);
1267
Francois Romieuffc46952012-07-06 14:19:23 +02001268 rtl_udelay_loop_wait_low(tp, &rtl_eriar_cond, 100, 100);
Hayes Wang133ac402011-07-06 15:58:05 +08001269}
1270
Francois Romieufdf6fc02012-07-06 22:40:38 +02001271static u32 rtl_eri_read(struct rtl8169_private *tp, int addr, int type)
Hayes Wang133ac402011-07-06 15:58:05 +08001272{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001273 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang133ac402011-07-06 15:58:05 +08001274
1275 RTL_W32(ERIAR, ERIAR_READ_CMD | type | ERIAR_MASK_1111 | addr);
1276
Francois Romieuffc46952012-07-06 14:19:23 +02001277 return rtl_udelay_loop_wait_high(tp, &rtl_eriar_cond, 100, 100) ?
1278 RTL_R32(ERIDR) : ~0;
Hayes Wang133ac402011-07-06 15:58:05 +08001279}
1280
Francois Romieufdf6fc02012-07-06 22:40:38 +02001281static void rtl_w1w0_eri(struct rtl8169_private *tp, int addr, u32 mask, u32 p,
1282 u32 m, int type)
Hayes Wang133ac402011-07-06 15:58:05 +08001283{
1284 u32 val;
1285
Francois Romieufdf6fc02012-07-06 22:40:38 +02001286 val = rtl_eri_read(tp, addr, type);
1287 rtl_eri_write(tp, addr, mask, (val & ~m) | p, type);
Hayes Wang133ac402011-07-06 15:58:05 +08001288}
1289
françois romieuc28aa382011-08-02 03:53:43 +00001290struct exgmac_reg {
1291 u16 addr;
1292 u16 mask;
1293 u32 val;
1294};
1295
Francois Romieufdf6fc02012-07-06 22:40:38 +02001296static void rtl_write_exgmac_batch(struct rtl8169_private *tp,
françois romieuc28aa382011-08-02 03:53:43 +00001297 const struct exgmac_reg *r, int len)
1298{
1299 while (len-- > 0) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001300 rtl_eri_write(tp, r->addr, r->mask, r->val, ERIAR_EXGMAC);
françois romieuc28aa382011-08-02 03:53:43 +00001301 r++;
1302 }
1303}
1304
Francois Romieuffc46952012-07-06 14:19:23 +02001305DECLARE_RTL_COND(rtl_efusear_cond)
1306{
1307 void __iomem *ioaddr = tp->mmio_addr;
1308
1309 return RTL_R32(EFUSEAR) & EFUSEAR_FLAG;
1310}
1311
Francois Romieufdf6fc02012-07-06 22:40:38 +02001312static u8 rtl8168d_efuse_read(struct rtl8169_private *tp, int reg_addr)
françois romieudaf9df62009-10-07 12:44:20 +00001313{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001314 void __iomem *ioaddr = tp->mmio_addr;
françois romieudaf9df62009-10-07 12:44:20 +00001315
1316 RTL_W32(EFUSEAR, (reg_addr & EFUSEAR_REG_MASK) << EFUSEAR_REG_SHIFT);
1317
Francois Romieuffc46952012-07-06 14:19:23 +02001318 return rtl_udelay_loop_wait_high(tp, &rtl_efusear_cond, 100, 300) ?
1319 RTL_R32(EFUSEAR) & EFUSEAR_DATA_MASK : ~0;
françois romieudaf9df62009-10-07 12:44:20 +00001320}
1321
Francois Romieu9085cdfa2012-01-26 12:59:08 +01001322static u16 rtl_get_events(struct rtl8169_private *tp)
1323{
1324 void __iomem *ioaddr = tp->mmio_addr;
1325
1326 return RTL_R16(IntrStatus);
1327}
1328
1329static void rtl_ack_events(struct rtl8169_private *tp, u16 bits)
1330{
1331 void __iomem *ioaddr = tp->mmio_addr;
1332
1333 RTL_W16(IntrStatus, bits);
1334 mmiowb();
1335}
1336
1337static void rtl_irq_disable(struct rtl8169_private *tp)
1338{
1339 void __iomem *ioaddr = tp->mmio_addr;
1340
1341 RTL_W16(IntrMask, 0);
1342 mmiowb();
1343}
1344
Francois Romieu3e990ff2012-01-26 12:50:01 +01001345static void rtl_irq_enable(struct rtl8169_private *tp, u16 bits)
1346{
1347 void __iomem *ioaddr = tp->mmio_addr;
1348
1349 RTL_W16(IntrMask, bits);
1350}
1351
Francois Romieuda78dbf2012-01-26 14:18:23 +01001352#define RTL_EVENT_NAPI_RX (RxOK | RxErr)
1353#define RTL_EVENT_NAPI_TX (TxOK | TxErr)
1354#define RTL_EVENT_NAPI (RTL_EVENT_NAPI_RX | RTL_EVENT_NAPI_TX)
1355
1356static void rtl_irq_enable_all(struct rtl8169_private *tp)
1357{
1358 rtl_irq_enable(tp, RTL_EVENT_NAPI | tp->event_slow);
1359}
1360
françois romieu811fd302011-12-04 20:30:45 +00001361static void rtl8169_irq_mask_and_ack(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362{
françois romieu811fd302011-12-04 20:30:45 +00001363 void __iomem *ioaddr = tp->mmio_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364
Francois Romieu9085cdfa2012-01-26 12:59:08 +01001365 rtl_irq_disable(tp);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001366 rtl_ack_events(tp, RTL_EVENT_NAPI | tp->event_slow);
françois romieu811fd302011-12-04 20:30:45 +00001367 RTL_R8(ChipCmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368}
1369
françois romieu4da19632011-01-03 15:07:55 +00001370static unsigned int rtl8169_tbi_reset_pending(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371{
françois romieu4da19632011-01-03 15:07:55 +00001372 void __iomem *ioaddr = tp->mmio_addr;
1373
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374 return RTL_R32(TBICSR) & TBIReset;
1375}
1376
françois romieu4da19632011-01-03 15:07:55 +00001377static unsigned int rtl8169_xmii_reset_pending(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378{
françois romieu4da19632011-01-03 15:07:55 +00001379 return rtl_readphy(tp, MII_BMCR) & BMCR_RESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380}
1381
1382static unsigned int rtl8169_tbi_link_ok(void __iomem *ioaddr)
1383{
1384 return RTL_R32(TBICSR) & TBILinkOk;
1385}
1386
1387static unsigned int rtl8169_xmii_link_ok(void __iomem *ioaddr)
1388{
1389 return RTL_R8(PHYstatus) & LinkStatus;
1390}
1391
françois romieu4da19632011-01-03 15:07:55 +00001392static void rtl8169_tbi_reset_enable(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393{
françois romieu4da19632011-01-03 15:07:55 +00001394 void __iomem *ioaddr = tp->mmio_addr;
1395
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396 RTL_W32(TBICSR, RTL_R32(TBICSR) | TBIReset);
1397}
1398
françois romieu4da19632011-01-03 15:07:55 +00001399static void rtl8169_xmii_reset_enable(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400{
1401 unsigned int val;
1402
françois romieu4da19632011-01-03 15:07:55 +00001403 val = rtl_readphy(tp, MII_BMCR) | BMCR_RESET;
1404 rtl_writephy(tp, MII_BMCR, val & 0xffff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405}
1406
Hayes Wang70090422011-07-06 15:58:06 +08001407static void rtl_link_chg_patch(struct rtl8169_private *tp)
1408{
1409 void __iomem *ioaddr = tp->mmio_addr;
1410 struct net_device *dev = tp->dev;
1411
1412 if (!netif_running(dev))
1413 return;
1414
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08001415 if (tp->mac_version == RTL_GIGA_MAC_VER_34 ||
1416 tp->mac_version == RTL_GIGA_MAC_VER_38) {
Hayes Wang70090422011-07-06 15:58:06 +08001417 if (RTL_R8(PHYstatus) & _1000bpsF) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001418 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x00000011,
1419 ERIAR_EXGMAC);
1420 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005,
1421 ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08001422 } else if (RTL_R8(PHYstatus) & _100bps) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001423 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f,
1424 ERIAR_EXGMAC);
1425 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005,
1426 ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08001427 } else {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001428 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f,
1429 ERIAR_EXGMAC);
1430 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x0000003f,
1431 ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08001432 }
1433 /* Reset packet filter */
Francois Romieufdf6fc02012-07-06 22:40:38 +02001434 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01,
Hayes Wang70090422011-07-06 15:58:06 +08001435 ERIAR_EXGMAC);
Francois Romieufdf6fc02012-07-06 22:40:38 +02001436 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00,
Hayes Wang70090422011-07-06 15:58:06 +08001437 ERIAR_EXGMAC);
Hayes Wangc2218922011-09-06 16:55:18 +08001438 } else if (tp->mac_version == RTL_GIGA_MAC_VER_35 ||
1439 tp->mac_version == RTL_GIGA_MAC_VER_36) {
1440 if (RTL_R8(PHYstatus) & _1000bpsF) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001441 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x00000011,
1442 ERIAR_EXGMAC);
1443 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005,
1444 ERIAR_EXGMAC);
Hayes Wangc2218922011-09-06 16:55:18 +08001445 } else {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001446 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f,
1447 ERIAR_EXGMAC);
1448 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x0000003f,
1449 ERIAR_EXGMAC);
Hayes Wangc2218922011-09-06 16:55:18 +08001450 }
Hayes Wang7e18dca2012-03-30 14:33:02 +08001451 } else if (tp->mac_version == RTL_GIGA_MAC_VER_37) {
1452 if (RTL_R8(PHYstatus) & _10bps) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001453 rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x4d02,
1454 ERIAR_EXGMAC);
1455 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_0011, 0x0060,
1456 ERIAR_EXGMAC);
Hayes Wang7e18dca2012-03-30 14:33:02 +08001457 } else {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001458 rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000,
1459 ERIAR_EXGMAC);
Hayes Wang7e18dca2012-03-30 14:33:02 +08001460 }
Hayes Wang70090422011-07-06 15:58:06 +08001461 }
1462}
1463
Rafael J. Wysockie4fbce72010-12-08 15:32:14 +00001464static void __rtl8169_check_link_status(struct net_device *dev,
Francois Romieucecb5fd2011-04-01 10:21:07 +02001465 struct rtl8169_private *tp,
1466 void __iomem *ioaddr, bool pm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 if (tp->link_ok(ioaddr)) {
Hayes Wang70090422011-07-06 15:58:06 +08001469 rtl_link_chg_patch(tp);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001470 /* This is to cancel a scheduled suspend if there's one. */
Rafael J. Wysockie4fbce72010-12-08 15:32:14 +00001471 if (pm)
1472 pm_request_resume(&tp->pci_dev->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473 netif_carrier_on(dev);
Francois Romieu1519e572011-02-03 12:02:36 +01001474 if (net_ratelimit())
1475 netif_info(tp, ifup, dev, "link up\n");
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +02001476 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477 netif_carrier_off(dev);
Joe Perchesbf82c182010-02-09 11:49:50 +00001478 netif_info(tp, ifdown, dev, "link down\n");
Rafael J. Wysockie4fbce72010-12-08 15:32:14 +00001479 if (pm)
hayeswang10953db2011-11-07 20:44:37 +00001480 pm_schedule_suspend(&tp->pci_dev->dev, 5000);
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +02001481 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482}
1483
Rafael J. Wysockie4fbce72010-12-08 15:32:14 +00001484static void rtl8169_check_link_status(struct net_device *dev,
1485 struct rtl8169_private *tp,
1486 void __iomem *ioaddr)
1487{
1488 __rtl8169_check_link_status(dev, tp, ioaddr, false);
1489}
1490
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001491#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST)
1492
1493static u32 __rtl8169_get_wol(struct rtl8169_private *tp)
1494{
1495 void __iomem *ioaddr = tp->mmio_addr;
1496 u8 options;
1497 u32 wolopts = 0;
1498
1499 options = RTL_R8(Config1);
1500 if (!(options & PMEnable))
1501 return 0;
1502
1503 options = RTL_R8(Config3);
1504 if (options & LinkUp)
1505 wolopts |= WAKE_PHY;
1506 if (options & MagicPacket)
1507 wolopts |= WAKE_MAGIC;
1508
1509 options = RTL_R8(Config5);
1510 if (options & UWF)
1511 wolopts |= WAKE_UCAST;
1512 if (options & BWF)
1513 wolopts |= WAKE_BCAST;
1514 if (options & MWF)
1515 wolopts |= WAKE_MCAST;
1516
1517 return wolopts;
1518}
1519
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001520static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
1521{
1522 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001523
Francois Romieuda78dbf2012-01-26 14:18:23 +01001524 rtl_lock_work(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001525
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001526 wol->supported = WAKE_ANY;
1527 wol->wolopts = __rtl8169_get_wol(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001528
Francois Romieuda78dbf2012-01-26 14:18:23 +01001529 rtl_unlock_work(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001530}
1531
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001532static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001533{
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001534 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu07d3f512007-02-21 22:40:46 +01001535 unsigned int i;
Alexey Dobriyan350f7592009-11-25 15:54:21 -08001536 static const struct {
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001537 u32 opt;
1538 u16 reg;
1539 u8 mask;
1540 } cfg[] = {
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001541 { WAKE_PHY, Config3, LinkUp },
1542 { WAKE_MAGIC, Config3, MagicPacket },
1543 { WAKE_UCAST, Config5, UWF },
1544 { WAKE_BCAST, Config5, BWF },
1545 { WAKE_MCAST, Config5, MWF },
1546 { WAKE_ANY, Config5, LanWake }
1547 };
Francois Romieu851e6022012-04-17 11:10:11 +02001548 u8 options;
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001549
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001550 RTL_W8(Cfg9346, Cfg9346_Unlock);
1551
1552 for (i = 0; i < ARRAY_SIZE(cfg); i++) {
Francois Romieu851e6022012-04-17 11:10:11 +02001553 options = RTL_R8(cfg[i].reg) & ~cfg[i].mask;
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001554 if (wolopts & cfg[i].opt)
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001555 options |= cfg[i].mask;
1556 RTL_W8(cfg[i].reg, options);
1557 }
1558
Francois Romieu851e6022012-04-17 11:10:11 +02001559 switch (tp->mac_version) {
1560 case RTL_GIGA_MAC_VER_01 ... RTL_GIGA_MAC_VER_17:
1561 options = RTL_R8(Config1) & ~PMEnable;
1562 if (wolopts)
1563 options |= PMEnable;
1564 RTL_W8(Config1, options);
1565 break;
1566 default:
Francois Romieud387b422012-04-17 11:12:01 +02001567 options = RTL_R8(Config2) & ~PME_SIGNAL;
1568 if (wolopts)
1569 options |= PME_SIGNAL;
1570 RTL_W8(Config2, options);
Francois Romieu851e6022012-04-17 11:10:11 +02001571 break;
1572 }
1573
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001574 RTL_W8(Cfg9346, Cfg9346_Lock);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001575}
1576
1577static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
1578{
1579 struct rtl8169_private *tp = netdev_priv(dev);
1580
Francois Romieuda78dbf2012-01-26 14:18:23 +01001581 rtl_lock_work(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001582
Francois Romieuf23e7fd2007-10-04 22:36:14 +02001583 if (wol->wolopts)
1584 tp->features |= RTL_FEATURE_WOL;
1585 else
1586 tp->features &= ~RTL_FEATURE_WOL;
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001587 __rtl8169_set_wol(tp, wol->wolopts);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001588
1589 rtl_unlock_work(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001590
françois romieuea809072010-11-08 13:23:58 +00001591 device_set_wakeup_enable(&tp->pci_dev->dev, wol->wolopts);
1592
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001593 return 0;
1594}
1595
Francois Romieu31bd2042011-04-26 18:58:59 +02001596static const char *rtl_lookup_firmware_name(struct rtl8169_private *tp)
1597{
Francois Romieu85bffe62011-04-27 08:22:39 +02001598 return rtl_chip_infos[tp->mac_version].fw_name;
Francois Romieu31bd2042011-04-26 18:58:59 +02001599}
1600
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601static void rtl8169_get_drvinfo(struct net_device *dev,
1602 struct ethtool_drvinfo *info)
1603{
1604 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieub6ffd972011-06-17 17:00:05 +02001605 struct rtl_fw *rtl_fw = tp->rtl_fw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001606
Rick Jones68aad782011-11-07 13:29:27 +00001607 strlcpy(info->driver, MODULENAME, sizeof(info->driver));
1608 strlcpy(info->version, RTL8169_VERSION, sizeof(info->version));
1609 strlcpy(info->bus_info, pci_name(tp->pci_dev), sizeof(info->bus_info));
Francois Romieu1c361ef2011-06-17 17:16:24 +02001610 BUILD_BUG_ON(sizeof(info->fw_version) < sizeof(rtl_fw->version));
Rick Jones8ac72d12011-11-22 14:06:26 +00001611 if (!IS_ERR_OR_NULL(rtl_fw))
1612 strlcpy(info->fw_version, rtl_fw->version,
1613 sizeof(info->fw_version));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614}
1615
1616static int rtl8169_get_regs_len(struct net_device *dev)
1617{
1618 return R8169_REGS_SIZE;
1619}
1620
1621static int rtl8169_set_speed_tbi(struct net_device *dev,
Oliver Neukum54405cd2011-01-06 21:55:13 +01001622 u8 autoneg, u16 speed, u8 duplex, u32 ignored)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623{
1624 struct rtl8169_private *tp = netdev_priv(dev);
1625 void __iomem *ioaddr = tp->mmio_addr;
1626 int ret = 0;
1627 u32 reg;
1628
1629 reg = RTL_R32(TBICSR);
1630 if ((autoneg == AUTONEG_DISABLE) && (speed == SPEED_1000) &&
1631 (duplex == DUPLEX_FULL)) {
1632 RTL_W32(TBICSR, reg & ~(TBINwEnable | TBINwRestart));
1633 } else if (autoneg == AUTONEG_ENABLE)
1634 RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart);
1635 else {
Joe Perchesbf82c182010-02-09 11:49:50 +00001636 netif_warn(tp, link, dev,
1637 "incorrect speed setting refused in TBI mode\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638 ret = -EOPNOTSUPP;
1639 }
1640
1641 return ret;
1642}
1643
1644static int rtl8169_set_speed_xmii(struct net_device *dev,
Oliver Neukum54405cd2011-01-06 21:55:13 +01001645 u8 autoneg, u16 speed, u8 duplex, u32 adv)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646{
1647 struct rtl8169_private *tp = netdev_priv(dev);
françois romieu3577aa12009-05-19 10:46:48 +00001648 int giga_ctrl, bmcr;
Oliver Neukum54405cd2011-01-06 21:55:13 +01001649 int rc = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001650
Hayes Wang716b50a2011-02-22 17:26:18 +08001651 rtl_writephy(tp, 0x1f, 0x0000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652
1653 if (autoneg == AUTONEG_ENABLE) {
françois romieu3577aa12009-05-19 10:46:48 +00001654 int auto_nego;
1655
françois romieu4da19632011-01-03 15:07:55 +00001656 auto_nego = rtl_readphy(tp, MII_ADVERTISE);
Oliver Neukum54405cd2011-01-06 21:55:13 +01001657 auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL |
1658 ADVERTISE_100HALF | ADVERTISE_100FULL);
1659
1660 if (adv & ADVERTISED_10baseT_Half)
1661 auto_nego |= ADVERTISE_10HALF;
1662 if (adv & ADVERTISED_10baseT_Full)
1663 auto_nego |= ADVERTISE_10FULL;
1664 if (adv & ADVERTISED_100baseT_Half)
1665 auto_nego |= ADVERTISE_100HALF;
1666 if (adv & ADVERTISED_100baseT_Full)
1667 auto_nego |= ADVERTISE_100FULL;
1668
françois romieu3577aa12009-05-19 10:46:48 +00001669 auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
1670
françois romieu4da19632011-01-03 15:07:55 +00001671 giga_ctrl = rtl_readphy(tp, MII_CTRL1000);
françois romieu3577aa12009-05-19 10:46:48 +00001672 giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
1673
1674 /* The 8100e/8101e/8102e do Fast Ethernet only. */
Francois Romieu826e6cb2011-03-11 20:30:24 +01001675 if (tp->mii.supports_gmii) {
Oliver Neukum54405cd2011-01-06 21:55:13 +01001676 if (adv & ADVERTISED_1000baseT_Half)
1677 giga_ctrl |= ADVERTISE_1000HALF;
1678 if (adv & ADVERTISED_1000baseT_Full)
1679 giga_ctrl |= ADVERTISE_1000FULL;
1680 } else if (adv & (ADVERTISED_1000baseT_Half |
1681 ADVERTISED_1000baseT_Full)) {
Joe Perchesbf82c182010-02-09 11:49:50 +00001682 netif_info(tp, link, dev,
1683 "PHY does not support 1000Mbps\n");
Oliver Neukum54405cd2011-01-06 21:55:13 +01001684 goto out;
Francois Romieubcf0bf92006-07-26 23:14:13 +02001685 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001686
françois romieu3577aa12009-05-19 10:46:48 +00001687 bmcr = BMCR_ANENABLE | BMCR_ANRESTART;
Francois Romieu623a1592006-05-14 12:42:14 +02001688
françois romieu4da19632011-01-03 15:07:55 +00001689 rtl_writephy(tp, MII_ADVERTISE, auto_nego);
1690 rtl_writephy(tp, MII_CTRL1000, giga_ctrl);
françois romieu3577aa12009-05-19 10:46:48 +00001691 } else {
1692 giga_ctrl = 0;
1693
1694 if (speed == SPEED_10)
1695 bmcr = 0;
1696 else if (speed == SPEED_100)
1697 bmcr = BMCR_SPEED100;
1698 else
Oliver Neukum54405cd2011-01-06 21:55:13 +01001699 goto out;
françois romieu3577aa12009-05-19 10:46:48 +00001700
1701 if (duplex == DUPLEX_FULL)
1702 bmcr |= BMCR_FULLDPLX;
Roger So2584fbc2007-07-31 23:52:42 +02001703 }
1704
françois romieu4da19632011-01-03 15:07:55 +00001705 rtl_writephy(tp, MII_BMCR, bmcr);
françois romieu3577aa12009-05-19 10:46:48 +00001706
Francois Romieucecb5fd2011-04-01 10:21:07 +02001707 if (tp->mac_version == RTL_GIGA_MAC_VER_02 ||
1708 tp->mac_version == RTL_GIGA_MAC_VER_03) {
françois romieu3577aa12009-05-19 10:46:48 +00001709 if ((speed == SPEED_100) && (autoneg != AUTONEG_ENABLE)) {
françois romieu4da19632011-01-03 15:07:55 +00001710 rtl_writephy(tp, 0x17, 0x2138);
1711 rtl_writephy(tp, 0x0e, 0x0260);
françois romieu3577aa12009-05-19 10:46:48 +00001712 } else {
françois romieu4da19632011-01-03 15:07:55 +00001713 rtl_writephy(tp, 0x17, 0x2108);
1714 rtl_writephy(tp, 0x0e, 0x0000);
françois romieu3577aa12009-05-19 10:46:48 +00001715 }
1716 }
1717
Oliver Neukum54405cd2011-01-06 21:55:13 +01001718 rc = 0;
1719out:
1720 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721}
1722
1723static int rtl8169_set_speed(struct net_device *dev,
Oliver Neukum54405cd2011-01-06 21:55:13 +01001724 u8 autoneg, u16 speed, u8 duplex, u32 advertising)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725{
1726 struct rtl8169_private *tp = netdev_priv(dev);
1727 int ret;
1728
Oliver Neukum54405cd2011-01-06 21:55:13 +01001729 ret = tp->set_speed(dev, autoneg, speed, duplex, advertising);
Francois Romieu4876cc12011-03-11 21:07:11 +01001730 if (ret < 0)
1731 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732
Francois Romieu4876cc12011-03-11 21:07:11 +01001733 if (netif_running(dev) && (autoneg == AUTONEG_ENABLE) &&
1734 (advertising & ADVERTISED_1000baseT_Full)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735 mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT);
Francois Romieu4876cc12011-03-11 21:07:11 +01001736 }
1737out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001738 return ret;
1739}
1740
1741static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
1742{
1743 struct rtl8169_private *tp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001744 int ret;
1745
Francois Romieu4876cc12011-03-11 21:07:11 +01001746 del_timer_sync(&tp->timer);
1747
Francois Romieuda78dbf2012-01-26 14:18:23 +01001748 rtl_lock_work(tp);
Francois Romieucecb5fd2011-04-01 10:21:07 +02001749 ret = rtl8169_set_speed(dev, cmd->autoneg, ethtool_cmd_speed(cmd),
David Decotigny25db0332011-04-27 18:32:39 +00001750 cmd->duplex, cmd->advertising);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001751 rtl_unlock_work(tp);
Francois Romieu5b0384f2006-08-16 16:00:01 +02001752
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753 return ret;
1754}
1755
Michał Mirosławc8f44af2011-11-15 15:29:55 +00001756static netdev_features_t rtl8169_fix_features(struct net_device *dev,
1757 netdev_features_t features)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001758{
Francois Romieud58d46b2011-05-03 16:38:29 +02001759 struct rtl8169_private *tp = netdev_priv(dev);
1760
Francois Romieu2b7b4312011-04-18 22:53:24 -07001761 if (dev->mtu > TD_MSS_MAX)
Michał Mirosław350fb322011-04-08 06:35:56 +00001762 features &= ~NETIF_F_ALL_TSO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001763
Francois Romieud58d46b2011-05-03 16:38:29 +02001764 if (dev->mtu > JUMBO_1K &&
1765 !rtl_chip_infos[tp->mac_version].jumbo_tx_csum)
1766 features &= ~NETIF_F_IP_CSUM;
1767
Michał Mirosław350fb322011-04-08 06:35:56 +00001768 return features;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001769}
1770
Francois Romieuda78dbf2012-01-26 14:18:23 +01001771static void __rtl8169_set_features(struct net_device *dev,
1772 netdev_features_t features)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001773{
1774 struct rtl8169_private *tp = netdev_priv(dev);
Ben Greear6bbe0212012-02-10 15:04:33 +00001775 netdev_features_t changed = features ^ dev->features;
Francois Romieuda78dbf2012-01-26 14:18:23 +01001776 void __iomem *ioaddr = tp->mmio_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001777
Ben Greear6bbe0212012-02-10 15:04:33 +00001778 if (!(changed & (NETIF_F_RXALL | NETIF_F_RXCSUM | NETIF_F_HW_VLAN_RX)))
1779 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001780
Ben Greear6bbe0212012-02-10 15:04:33 +00001781 if (changed & (NETIF_F_RXCSUM | NETIF_F_HW_VLAN_RX)) {
1782 if (features & NETIF_F_RXCSUM)
1783 tp->cp_cmd |= RxChkSum;
1784 else
1785 tp->cp_cmd &= ~RxChkSum;
Michał Mirosław350fb322011-04-08 06:35:56 +00001786
Ben Greear6bbe0212012-02-10 15:04:33 +00001787 if (dev->features & NETIF_F_HW_VLAN_RX)
1788 tp->cp_cmd |= RxVlan;
1789 else
1790 tp->cp_cmd &= ~RxVlan;
1791
1792 RTL_W16(CPlusCmd, tp->cp_cmd);
1793 RTL_R16(CPlusCmd);
1794 }
1795 if (changed & NETIF_F_RXALL) {
1796 int tmp = (RTL_R32(RxConfig) & ~(AcceptErr | AcceptRunt));
1797 if (features & NETIF_F_RXALL)
1798 tmp |= (AcceptErr | AcceptRunt);
1799 RTL_W32(RxConfig, tmp);
1800 }
Francois Romieuda78dbf2012-01-26 14:18:23 +01001801}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001802
Francois Romieuda78dbf2012-01-26 14:18:23 +01001803static int rtl8169_set_features(struct net_device *dev,
1804 netdev_features_t features)
1805{
1806 struct rtl8169_private *tp = netdev_priv(dev);
1807
1808 rtl_lock_work(tp);
1809 __rtl8169_set_features(dev, features);
1810 rtl_unlock_work(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001811
1812 return 0;
1813}
1814
Francois Romieuda78dbf2012-01-26 14:18:23 +01001815
Kirill Smelkov810f4892012-11-10 21:11:02 +04001816static inline u32 rtl8169_tx_vlan_tag(struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001817{
Jesse Grosseab6d182010-10-20 13:56:03 +00001818 return (vlan_tx_tag_present(skb)) ?
Linus Torvalds1da177e2005-04-16 15:20:36 -07001819 TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00;
1820}
1821
Francois Romieu7a8fc772011-03-01 17:18:33 +01001822static void rtl8169_rx_vlan_tag(struct RxDesc *desc, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823{
1824 u32 opts2 = le32_to_cpu(desc->opts2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001825
Francois Romieu7a8fc772011-03-01 17:18:33 +01001826 if (opts2 & RxVlanTag)
1827 __vlan_hwaccel_put_tag(skb, swab16(opts2 & 0xffff));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828}
1829
Francois Romieuccdffb92008-07-26 14:26:06 +02001830static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831{
1832 struct rtl8169_private *tp = netdev_priv(dev);
1833 void __iomem *ioaddr = tp->mmio_addr;
1834 u32 status;
1835
1836 cmd->supported =
1837 SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE;
1838 cmd->port = PORT_FIBRE;
1839 cmd->transceiver = XCVR_INTERNAL;
1840
1841 status = RTL_R32(TBICSR);
1842 cmd->advertising = (status & TBINwEnable) ? ADVERTISED_Autoneg : 0;
1843 cmd->autoneg = !!(status & TBINwEnable);
1844
David Decotigny70739492011-04-27 18:32:40 +00001845 ethtool_cmd_speed_set(cmd, SPEED_1000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001846 cmd->duplex = DUPLEX_FULL; /* Always set */
Francois Romieuccdffb92008-07-26 14:26:06 +02001847
1848 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001849}
1850
Francois Romieuccdffb92008-07-26 14:26:06 +02001851static int rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852{
1853 struct rtl8169_private *tp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001854
Francois Romieuccdffb92008-07-26 14:26:06 +02001855 return mii_ethtool_gset(&tp->mii, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856}
1857
1858static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
1859{
1860 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieuccdffb92008-07-26 14:26:06 +02001861 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862
Francois Romieuda78dbf2012-01-26 14:18:23 +01001863 rtl_lock_work(tp);
Francois Romieuccdffb92008-07-26 14:26:06 +02001864 rc = tp->get_settings(dev, cmd);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001865 rtl_unlock_work(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001866
Francois Romieuccdffb92008-07-26 14:26:06 +02001867 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868}
1869
1870static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs,
1871 void *p)
1872{
Francois Romieu5b0384f2006-08-16 16:00:01 +02001873 struct rtl8169_private *tp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001874
Francois Romieu5b0384f2006-08-16 16:00:01 +02001875 if (regs->len > R8169_REGS_SIZE)
1876 regs->len = R8169_REGS_SIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877
Francois Romieuda78dbf2012-01-26 14:18:23 +01001878 rtl_lock_work(tp);
Francois Romieu5b0384f2006-08-16 16:00:01 +02001879 memcpy_fromio(p, tp->mmio_addr, regs->len);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001880 rtl_unlock_work(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001881}
1882
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +02001883static u32 rtl8169_get_msglevel(struct net_device *dev)
1884{
1885 struct rtl8169_private *tp = netdev_priv(dev);
1886
1887 return tp->msg_enable;
1888}
1889
1890static void rtl8169_set_msglevel(struct net_device *dev, u32 value)
1891{
1892 struct rtl8169_private *tp = netdev_priv(dev);
1893
1894 tp->msg_enable = value;
1895}
1896
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001897static const char rtl8169_gstrings[][ETH_GSTRING_LEN] = {
1898 "tx_packets",
1899 "rx_packets",
1900 "tx_errors",
1901 "rx_errors",
1902 "rx_missed",
1903 "align_errors",
1904 "tx_single_collisions",
1905 "tx_multi_collisions",
1906 "unicast",
1907 "broadcast",
1908 "multicast",
1909 "tx_aborted",
1910 "tx_underrun",
1911};
1912
Jeff Garzikb9f2c042007-10-03 18:07:32 -07001913static int rtl8169_get_sset_count(struct net_device *dev, int sset)
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001914{
Jeff Garzikb9f2c042007-10-03 18:07:32 -07001915 switch (sset) {
1916 case ETH_SS_STATS:
1917 return ARRAY_SIZE(rtl8169_gstrings);
1918 default:
1919 return -EOPNOTSUPP;
1920 }
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001921}
1922
Francois Romieuffc46952012-07-06 14:19:23 +02001923DECLARE_RTL_COND(rtl_counters_cond)
1924{
1925 void __iomem *ioaddr = tp->mmio_addr;
1926
1927 return RTL_R32(CounterAddrLow) & CounterDump;
1928}
1929
Ivan Vecera355423d2009-02-06 21:49:57 -08001930static void rtl8169_update_counters(struct net_device *dev)
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001931{
1932 struct rtl8169_private *tp = netdev_priv(dev);
1933 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieucecb5fd2011-04-01 10:21:07 +02001934 struct device *d = &tp->pci_dev->dev;
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001935 struct rtl8169_counters *counters;
1936 dma_addr_t paddr;
1937 u32 cmd;
1938
Ivan Vecera355423d2009-02-06 21:49:57 -08001939 /*
1940 * Some chips are unable to dump tally counters when the receiver
1941 * is disabled.
1942 */
1943 if ((RTL_R8(ChipCmd) & CmdRxEnb) == 0)
1944 return;
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001945
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00001946 counters = dma_alloc_coherent(d, sizeof(*counters), &paddr, GFP_KERNEL);
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001947 if (!counters)
1948 return;
1949
1950 RTL_W32(CounterAddrHigh, (u64)paddr >> 32);
Yang Hongyang284901a2009-04-06 19:01:15 -07001951 cmd = (u64)paddr & DMA_BIT_MASK(32);
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001952 RTL_W32(CounterAddrLow, cmd);
1953 RTL_W32(CounterAddrLow, cmd | CounterDump);
1954
Francois Romieuffc46952012-07-06 14:19:23 +02001955 if (rtl_udelay_loop_wait_low(tp, &rtl_counters_cond, 10, 1000))
1956 memcpy(&tp->counters, counters, sizeof(*counters));
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001957
1958 RTL_W32(CounterAddrLow, 0);
1959 RTL_W32(CounterAddrHigh, 0);
1960
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00001961 dma_free_coherent(d, sizeof(*counters), counters, paddr);
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001962}
1963
Ivan Vecera355423d2009-02-06 21:49:57 -08001964static void rtl8169_get_ethtool_stats(struct net_device *dev,
1965 struct ethtool_stats *stats, u64 *data)
1966{
1967 struct rtl8169_private *tp = netdev_priv(dev);
1968
1969 ASSERT_RTNL();
1970
1971 rtl8169_update_counters(dev);
1972
1973 data[0] = le64_to_cpu(tp->counters.tx_packets);
1974 data[1] = le64_to_cpu(tp->counters.rx_packets);
1975 data[2] = le64_to_cpu(tp->counters.tx_errors);
1976 data[3] = le32_to_cpu(tp->counters.rx_errors);
1977 data[4] = le16_to_cpu(tp->counters.rx_missed);
1978 data[5] = le16_to_cpu(tp->counters.align_errors);
1979 data[6] = le32_to_cpu(tp->counters.tx_one_collision);
1980 data[7] = le32_to_cpu(tp->counters.tx_multi_collision);
1981 data[8] = le64_to_cpu(tp->counters.rx_unicast);
1982 data[9] = le64_to_cpu(tp->counters.rx_broadcast);
1983 data[10] = le32_to_cpu(tp->counters.rx_multicast);
1984 data[11] = le16_to_cpu(tp->counters.tx_aborted);
1985 data[12] = le16_to_cpu(tp->counters.tx_underun);
1986}
1987
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001988static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data)
1989{
1990 switch(stringset) {
1991 case ETH_SS_STATS:
1992 memcpy(data, *rtl8169_gstrings, sizeof(rtl8169_gstrings));
1993 break;
1994 }
1995}
1996
Jeff Garzik7282d492006-09-13 14:30:00 -04001997static const struct ethtool_ops rtl8169_ethtool_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001998 .get_drvinfo = rtl8169_get_drvinfo,
1999 .get_regs_len = rtl8169_get_regs_len,
2000 .get_link = ethtool_op_get_link,
2001 .get_settings = rtl8169_get_settings,
2002 .set_settings = rtl8169_set_settings,
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +02002003 .get_msglevel = rtl8169_get_msglevel,
2004 .set_msglevel = rtl8169_set_msglevel,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002005 .get_regs = rtl8169_get_regs,
Francois Romieu61a4dcc2006-02-23 00:55:25 +01002006 .get_wol = rtl8169_get_wol,
2007 .set_wol = rtl8169_set_wol,
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02002008 .get_strings = rtl8169_get_strings,
Jeff Garzikb9f2c042007-10-03 18:07:32 -07002009 .get_sset_count = rtl8169_get_sset_count,
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02002010 .get_ethtool_stats = rtl8169_get_ethtool_stats,
Richard Cochrane1593bb2012-04-03 22:59:35 +00002011 .get_ts_info = ethtool_op_get_ts_info,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002012};
2013
Francois Romieu07d3f512007-02-21 22:40:46 +01002014static void rtl8169_get_mac_version(struct rtl8169_private *tp,
Francois Romieu5d320a22011-05-08 17:47:36 +02002015 struct net_device *dev, u8 default_version)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002016{
Francois Romieu5d320a22011-05-08 17:47:36 +02002017 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu0e485152007-02-20 00:00:26 +01002018 /*
2019 * The driver currently handles the 8168Bf and the 8168Be identically
2020 * but they can be identified more specifically through the test below
2021 * if needed:
2022 *
2023 * (RTL_R32(TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be
Francois Romieu01272152007-02-20 22:58:51 +01002024 *
2025 * Same thing for the 8101Eb and the 8101Ec:
2026 *
2027 * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec
Francois Romieu0e485152007-02-20 00:00:26 +01002028 */
Francois Romieu37441002011-06-17 22:58:54 +02002029 static const struct rtl_mac_info {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002030 u32 mask;
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002031 u32 val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002032 int mac_version;
2033 } mac_info[] = {
Hayes Wangc5583862012-07-02 17:23:22 +08002034 /* 8168G family. */
2035 { 0x7cf00000, 0x4c100000, RTL_GIGA_MAC_VER_41 },
2036 { 0x7cf00000, 0x4c000000, RTL_GIGA_MAC_VER_40 },
2037
Hayes Wangc2218922011-09-06 16:55:18 +08002038 /* 8168F family. */
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08002039 { 0x7c800000, 0x48800000, RTL_GIGA_MAC_VER_38 },
Hayes Wangc2218922011-09-06 16:55:18 +08002040 { 0x7cf00000, 0x48100000, RTL_GIGA_MAC_VER_36 },
2041 { 0x7cf00000, 0x48000000, RTL_GIGA_MAC_VER_35 },
2042
hayeswang01dc7fe2011-03-21 01:50:28 +00002043 /* 8168E family. */
Hayes Wang70090422011-07-06 15:58:06 +08002044 { 0x7c800000, 0x2c800000, RTL_GIGA_MAC_VER_34 },
hayeswang01dc7fe2011-03-21 01:50:28 +00002045 { 0x7cf00000, 0x2c200000, RTL_GIGA_MAC_VER_33 },
2046 { 0x7cf00000, 0x2c100000, RTL_GIGA_MAC_VER_32 },
2047 { 0x7c800000, 0x2c000000, RTL_GIGA_MAC_VER_33 },
2048
Francois Romieu5b538df2008-07-20 16:22:45 +02002049 /* 8168D family. */
françois romieudaf9df62009-10-07 12:44:20 +00002050 { 0x7cf00000, 0x28300000, RTL_GIGA_MAC_VER_26 },
2051 { 0x7cf00000, 0x28100000, RTL_GIGA_MAC_VER_25 },
françois romieudaf9df62009-10-07 12:44:20 +00002052 { 0x7c800000, 0x28000000, RTL_GIGA_MAC_VER_26 },
Francois Romieu5b538df2008-07-20 16:22:45 +02002053
françois romieue6de30d2011-01-03 15:08:37 +00002054 /* 8168DP family. */
2055 { 0x7cf00000, 0x28800000, RTL_GIGA_MAC_VER_27 },
2056 { 0x7cf00000, 0x28a00000, RTL_GIGA_MAC_VER_28 },
hayeswang4804b3b2011-03-21 01:50:29 +00002057 { 0x7cf00000, 0x28b00000, RTL_GIGA_MAC_VER_31 },
françois romieue6de30d2011-01-03 15:08:37 +00002058
Francois Romieuef808d52008-06-29 13:10:54 +02002059 /* 8168C family. */
Francois Romieu17c99292010-07-11 17:10:09 -07002060 { 0x7cf00000, 0x3cb00000, RTL_GIGA_MAC_VER_24 },
Francois Romieuef3386f2008-06-29 12:24:30 +02002061 { 0x7cf00000, 0x3c900000, RTL_GIGA_MAC_VER_23 },
Francois Romieuef808d52008-06-29 13:10:54 +02002062 { 0x7cf00000, 0x3c800000, RTL_GIGA_MAC_VER_18 },
Francois Romieu7f3e3d32008-07-20 18:53:20 +02002063 { 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_24 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002064 { 0x7cf00000, 0x3c000000, RTL_GIGA_MAC_VER_19 },
2065 { 0x7cf00000, 0x3c200000, RTL_GIGA_MAC_VER_20 },
Francois Romieu197ff762008-06-28 13:16:02 +02002066 { 0x7cf00000, 0x3c300000, RTL_GIGA_MAC_VER_21 },
Francois Romieu6fb07052008-06-29 11:54:28 +02002067 { 0x7cf00000, 0x3c400000, RTL_GIGA_MAC_VER_22 },
Francois Romieuef808d52008-06-29 13:10:54 +02002068 { 0x7c800000, 0x3c000000, RTL_GIGA_MAC_VER_22 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002069
2070 /* 8168B family. */
2071 { 0x7cf00000, 0x38000000, RTL_GIGA_MAC_VER_12 },
2072 { 0x7cf00000, 0x38500000, RTL_GIGA_MAC_VER_17 },
2073 { 0x7c800000, 0x38000000, RTL_GIGA_MAC_VER_17 },
2074 { 0x7c800000, 0x30000000, RTL_GIGA_MAC_VER_11 },
2075
2076 /* 8101 family. */
Hayes Wang5598bfe2012-07-02 17:23:21 +08002077 { 0x7cf00000, 0x44900000, RTL_GIGA_MAC_VER_39 },
2078 { 0x7c800000, 0x44800000, RTL_GIGA_MAC_VER_39 },
Hayes Wang7e18dca2012-03-30 14:33:02 +08002079 { 0x7c800000, 0x44000000, RTL_GIGA_MAC_VER_37 },
hayeswang36a0e6c2011-03-21 01:50:30 +00002080 { 0x7cf00000, 0x40b00000, RTL_GIGA_MAC_VER_30 },
Hayes Wang5a5e4442011-02-22 17:26:21 +08002081 { 0x7cf00000, 0x40a00000, RTL_GIGA_MAC_VER_30 },
2082 { 0x7cf00000, 0x40900000, RTL_GIGA_MAC_VER_29 },
2083 { 0x7c800000, 0x40800000, RTL_GIGA_MAC_VER_30 },
Francois Romieu2857ffb2008-08-02 21:08:49 +02002084 { 0x7cf00000, 0x34a00000, RTL_GIGA_MAC_VER_09 },
2085 { 0x7cf00000, 0x24a00000, RTL_GIGA_MAC_VER_09 },
2086 { 0x7cf00000, 0x34900000, RTL_GIGA_MAC_VER_08 },
2087 { 0x7cf00000, 0x24900000, RTL_GIGA_MAC_VER_08 },
2088 { 0x7cf00000, 0x34800000, RTL_GIGA_MAC_VER_07 },
2089 { 0x7cf00000, 0x24800000, RTL_GIGA_MAC_VER_07 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002090 { 0x7cf00000, 0x34000000, RTL_GIGA_MAC_VER_13 },
Francois Romieu2857ffb2008-08-02 21:08:49 +02002091 { 0x7cf00000, 0x34300000, RTL_GIGA_MAC_VER_10 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002092 { 0x7cf00000, 0x34200000, RTL_GIGA_MAC_VER_16 },
Francois Romieu2857ffb2008-08-02 21:08:49 +02002093 { 0x7c800000, 0x34800000, RTL_GIGA_MAC_VER_09 },
2094 { 0x7c800000, 0x24800000, RTL_GIGA_MAC_VER_09 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002095 { 0x7c800000, 0x34000000, RTL_GIGA_MAC_VER_16 },
2096 /* FIXME: where did these entries come from ? -- FR */
2097 { 0xfc800000, 0x38800000, RTL_GIGA_MAC_VER_15 },
2098 { 0xfc800000, 0x30800000, RTL_GIGA_MAC_VER_14 },
2099
2100 /* 8110 family. */
2101 { 0xfc800000, 0x98000000, RTL_GIGA_MAC_VER_06 },
2102 { 0xfc800000, 0x18000000, RTL_GIGA_MAC_VER_05 },
2103 { 0xfc800000, 0x10000000, RTL_GIGA_MAC_VER_04 },
2104 { 0xfc800000, 0x04000000, RTL_GIGA_MAC_VER_03 },
2105 { 0xfc800000, 0x00800000, RTL_GIGA_MAC_VER_02 },
2106 { 0xfc800000, 0x00000000, RTL_GIGA_MAC_VER_01 },
2107
Jean Delvaref21b75e2009-05-26 20:54:48 -07002108 /* Catch-all */
2109 { 0x00000000, 0x00000000, RTL_GIGA_MAC_NONE }
Francois Romieu37441002011-06-17 22:58:54 +02002110 };
2111 const struct rtl_mac_info *p = mac_info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002112 u32 reg;
2113
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002114 reg = RTL_R32(TxConfig);
2115 while ((reg & p->mask) != p->val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002116 p++;
2117 tp->mac_version = p->mac_version;
Francois Romieu5d320a22011-05-08 17:47:36 +02002118
2119 if (tp->mac_version == RTL_GIGA_MAC_NONE) {
2120 netif_notice(tp, probe, dev,
2121 "unknown MAC, using family default\n");
2122 tp->mac_version = default_version;
2123 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002124}
2125
2126static void rtl8169_print_mac_version(struct rtl8169_private *tp)
2127{
Francois Romieubcf0bf92006-07-26 23:14:13 +02002128 dprintk("mac_version = 0x%02x\n", tp->mac_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002129}
2130
Francois Romieu867763c2007-08-17 18:21:58 +02002131struct phy_reg {
2132 u16 reg;
2133 u16 val;
2134};
2135
françois romieu4da19632011-01-03 15:07:55 +00002136static void rtl_writephy_batch(struct rtl8169_private *tp,
2137 const struct phy_reg *regs, int len)
Francois Romieu867763c2007-08-17 18:21:58 +02002138{
2139 while (len-- > 0) {
françois romieu4da19632011-01-03 15:07:55 +00002140 rtl_writephy(tp, regs->reg, regs->val);
Francois Romieu867763c2007-08-17 18:21:58 +02002141 regs++;
2142 }
2143}
2144
françois romieubca03d52011-01-03 15:07:31 +00002145#define PHY_READ 0x00000000
2146#define PHY_DATA_OR 0x10000000
2147#define PHY_DATA_AND 0x20000000
2148#define PHY_BJMPN 0x30000000
2149#define PHY_READ_EFUSE 0x40000000
2150#define PHY_READ_MAC_BYTE 0x50000000
2151#define PHY_WRITE_MAC_BYTE 0x60000000
2152#define PHY_CLEAR_READCOUNT 0x70000000
2153#define PHY_WRITE 0x80000000
2154#define PHY_READCOUNT_EQ_SKIP 0x90000000
2155#define PHY_COMP_EQ_SKIPN 0xa0000000
2156#define PHY_COMP_NEQ_SKIPN 0xb0000000
2157#define PHY_WRITE_PREVIOUS 0xc0000000
2158#define PHY_SKIPN 0xd0000000
2159#define PHY_DELAY_MS 0xe0000000
2160#define PHY_WRITE_ERI_WORD 0xf0000000
2161
Hayes Wang960aee62011-06-18 11:37:48 +02002162struct fw_info {
2163 u32 magic;
2164 char version[RTL_VER_SIZE];
2165 __le32 fw_start;
2166 __le32 fw_len;
2167 u8 chksum;
2168} __packed;
2169
Francois Romieu1c361ef2011-06-17 17:16:24 +02002170#define FW_OPCODE_SIZE sizeof(typeof(*((struct rtl_fw_phy_action *)0)->code))
2171
2172static bool rtl_fw_format_ok(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
françois romieubca03d52011-01-03 15:07:31 +00002173{
Francois Romieub6ffd972011-06-17 17:00:05 +02002174 const struct firmware *fw = rtl_fw->fw;
Hayes Wang960aee62011-06-18 11:37:48 +02002175 struct fw_info *fw_info = (struct fw_info *)fw->data;
Francois Romieu1c361ef2011-06-17 17:16:24 +02002176 struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
2177 char *version = rtl_fw->version;
2178 bool rc = false;
françois romieubca03d52011-01-03 15:07:31 +00002179
Francois Romieu1c361ef2011-06-17 17:16:24 +02002180 if (fw->size < FW_OPCODE_SIZE)
2181 goto out;
Hayes Wang960aee62011-06-18 11:37:48 +02002182
2183 if (!fw_info->magic) {
2184 size_t i, size, start;
2185 u8 checksum = 0;
2186
2187 if (fw->size < sizeof(*fw_info))
2188 goto out;
2189
2190 for (i = 0; i < fw->size; i++)
2191 checksum += fw->data[i];
2192 if (checksum != 0)
2193 goto out;
2194
2195 start = le32_to_cpu(fw_info->fw_start);
2196 if (start > fw->size)
2197 goto out;
2198
2199 size = le32_to_cpu(fw_info->fw_len);
2200 if (size > (fw->size - start) / FW_OPCODE_SIZE)
2201 goto out;
2202
2203 memcpy(version, fw_info->version, RTL_VER_SIZE);
2204
2205 pa->code = (__le32 *)(fw->data + start);
2206 pa->size = size;
2207 } else {
Francois Romieu1c361ef2011-06-17 17:16:24 +02002208 if (fw->size % FW_OPCODE_SIZE)
2209 goto out;
2210
2211 strlcpy(version, rtl_lookup_firmware_name(tp), RTL_VER_SIZE);
2212
2213 pa->code = (__le32 *)fw->data;
2214 pa->size = fw->size / FW_OPCODE_SIZE;
2215 }
2216 version[RTL_VER_SIZE - 1] = 0;
2217
2218 rc = true;
2219out:
2220 return rc;
2221}
2222
Francois Romieufd112f22011-06-18 00:10:29 +02002223static bool rtl_fw_data_ok(struct rtl8169_private *tp, struct net_device *dev,
2224 struct rtl_fw_phy_action *pa)
Francois Romieu1c361ef2011-06-17 17:16:24 +02002225{
Francois Romieufd112f22011-06-18 00:10:29 +02002226 bool rc = false;
Francois Romieu1c361ef2011-06-17 17:16:24 +02002227 size_t index;
2228
Francois Romieu1c361ef2011-06-17 17:16:24 +02002229 for (index = 0; index < pa->size; index++) {
2230 u32 action = le32_to_cpu(pa->code[index]);
hayeswang42b82dc2011-01-10 02:07:25 +00002231 u32 regno = (action & 0x0fff0000) >> 16;
françois romieubca03d52011-01-03 15:07:31 +00002232
hayeswang42b82dc2011-01-10 02:07:25 +00002233 switch(action & 0xf0000000) {
2234 case PHY_READ:
2235 case PHY_DATA_OR:
2236 case PHY_DATA_AND:
2237 case PHY_READ_EFUSE:
2238 case PHY_CLEAR_READCOUNT:
2239 case PHY_WRITE:
2240 case PHY_WRITE_PREVIOUS:
2241 case PHY_DELAY_MS:
françois romieubca03d52011-01-03 15:07:31 +00002242 break;
2243
hayeswang42b82dc2011-01-10 02:07:25 +00002244 case PHY_BJMPN:
2245 if (regno > index) {
Francois Romieufd112f22011-06-18 00:10:29 +02002246 netif_err(tp, ifup, tp->dev,
Francois Romieucecb5fd2011-04-01 10:21:07 +02002247 "Out of range of firmware\n");
Francois Romieufd112f22011-06-18 00:10:29 +02002248 goto out;
hayeswang42b82dc2011-01-10 02:07:25 +00002249 }
2250 break;
2251 case PHY_READCOUNT_EQ_SKIP:
Francois Romieu1c361ef2011-06-17 17:16:24 +02002252 if (index + 2 >= pa->size) {
Francois Romieufd112f22011-06-18 00:10:29 +02002253 netif_err(tp, ifup, tp->dev,
Francois Romieucecb5fd2011-04-01 10:21:07 +02002254 "Out of range of firmware\n");
Francois Romieufd112f22011-06-18 00:10:29 +02002255 goto out;
hayeswang42b82dc2011-01-10 02:07:25 +00002256 }
2257 break;
2258 case PHY_COMP_EQ_SKIPN:
2259 case PHY_COMP_NEQ_SKIPN:
2260 case PHY_SKIPN:
Francois Romieu1c361ef2011-06-17 17:16:24 +02002261 if (index + 1 + regno >= pa->size) {
Francois Romieufd112f22011-06-18 00:10:29 +02002262 netif_err(tp, ifup, tp->dev,
Francois Romieucecb5fd2011-04-01 10:21:07 +02002263 "Out of range of firmware\n");
Francois Romieufd112f22011-06-18 00:10:29 +02002264 goto out;
hayeswang42b82dc2011-01-10 02:07:25 +00002265 }
2266 break;
2267
2268 case PHY_READ_MAC_BYTE:
2269 case PHY_WRITE_MAC_BYTE:
2270 case PHY_WRITE_ERI_WORD:
2271 default:
Francois Romieufd112f22011-06-18 00:10:29 +02002272 netif_err(tp, ifup, tp->dev,
hayeswang42b82dc2011-01-10 02:07:25 +00002273 "Invalid action 0x%08x\n", action);
Francois Romieufd112f22011-06-18 00:10:29 +02002274 goto out;
françois romieubca03d52011-01-03 15:07:31 +00002275 }
2276 }
Francois Romieufd112f22011-06-18 00:10:29 +02002277 rc = true;
2278out:
2279 return rc;
2280}
françois romieubca03d52011-01-03 15:07:31 +00002281
Francois Romieufd112f22011-06-18 00:10:29 +02002282static int rtl_check_firmware(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
2283{
2284 struct net_device *dev = tp->dev;
2285 int rc = -EINVAL;
2286
2287 if (!rtl_fw_format_ok(tp, rtl_fw)) {
2288 netif_err(tp, ifup, dev, "invalid firwmare\n");
2289 goto out;
2290 }
2291
2292 if (rtl_fw_data_ok(tp, dev, &rtl_fw->phy_action))
2293 rc = 0;
2294out:
2295 return rc;
2296}
2297
2298static void rtl_phy_write_fw(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
2299{
2300 struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
2301 u32 predata, count;
2302 size_t index;
2303
2304 predata = count = 0;
hayeswang42b82dc2011-01-10 02:07:25 +00002305
Francois Romieu1c361ef2011-06-17 17:16:24 +02002306 for (index = 0; index < pa->size; ) {
2307 u32 action = le32_to_cpu(pa->code[index]);
françois romieubca03d52011-01-03 15:07:31 +00002308 u32 data = action & 0x0000ffff;
hayeswang42b82dc2011-01-10 02:07:25 +00002309 u32 regno = (action & 0x0fff0000) >> 16;
2310
2311 if (!action)
2312 break;
françois romieubca03d52011-01-03 15:07:31 +00002313
2314 switch(action & 0xf0000000) {
hayeswang42b82dc2011-01-10 02:07:25 +00002315 case PHY_READ:
2316 predata = rtl_readphy(tp, regno);
2317 count++;
2318 index++;
françois romieubca03d52011-01-03 15:07:31 +00002319 break;
hayeswang42b82dc2011-01-10 02:07:25 +00002320 case PHY_DATA_OR:
2321 predata |= data;
2322 index++;
2323 break;
2324 case PHY_DATA_AND:
2325 predata &= data;
2326 index++;
2327 break;
2328 case PHY_BJMPN:
2329 index -= regno;
2330 break;
2331 case PHY_READ_EFUSE:
Francois Romieufdf6fc02012-07-06 22:40:38 +02002332 predata = rtl8168d_efuse_read(tp, regno);
hayeswang42b82dc2011-01-10 02:07:25 +00002333 index++;
2334 break;
2335 case PHY_CLEAR_READCOUNT:
2336 count = 0;
2337 index++;
2338 break;
2339 case PHY_WRITE:
2340 rtl_writephy(tp, regno, data);
2341 index++;
2342 break;
2343 case PHY_READCOUNT_EQ_SKIP:
Francois Romieucecb5fd2011-04-01 10:21:07 +02002344 index += (count == data) ? 2 : 1;
hayeswang42b82dc2011-01-10 02:07:25 +00002345 break;
2346 case PHY_COMP_EQ_SKIPN:
2347 if (predata == data)
2348 index += regno;
2349 index++;
2350 break;
2351 case PHY_COMP_NEQ_SKIPN:
2352 if (predata != data)
2353 index += regno;
2354 index++;
2355 break;
2356 case PHY_WRITE_PREVIOUS:
2357 rtl_writephy(tp, regno, predata);
2358 index++;
2359 break;
2360 case PHY_SKIPN:
2361 index += regno + 1;
2362 break;
2363 case PHY_DELAY_MS:
2364 mdelay(data);
2365 index++;
2366 break;
2367
2368 case PHY_READ_MAC_BYTE:
2369 case PHY_WRITE_MAC_BYTE:
2370 case PHY_WRITE_ERI_WORD:
françois romieubca03d52011-01-03 15:07:31 +00002371 default:
2372 BUG();
2373 }
2374 }
2375}
2376
françois romieuf1e02ed2011-01-13 13:07:53 +00002377static void rtl_release_firmware(struct rtl8169_private *tp)
2378{
Francois Romieub6ffd972011-06-17 17:00:05 +02002379 if (!IS_ERR_OR_NULL(tp->rtl_fw)) {
2380 release_firmware(tp->rtl_fw->fw);
2381 kfree(tp->rtl_fw);
2382 }
2383 tp->rtl_fw = RTL_FIRMWARE_UNKNOWN;
françois romieuf1e02ed2011-01-13 13:07:53 +00002384}
2385
François Romieu953a12c2011-04-24 17:38:48 +02002386static void rtl_apply_firmware(struct rtl8169_private *tp)
françois romieuf1e02ed2011-01-13 13:07:53 +00002387{
Francois Romieub6ffd972011-06-17 17:00:05 +02002388 struct rtl_fw *rtl_fw = tp->rtl_fw;
françois romieuf1e02ed2011-01-13 13:07:53 +00002389
2390 /* TODO: release firmware once rtl_phy_write_fw signals failures. */
Francois Romieueef63cc2013-02-08 23:43:20 +01002391 if (!IS_ERR_OR_NULL(rtl_fw))
Francois Romieub6ffd972011-06-17 17:00:05 +02002392 rtl_phy_write_fw(tp, rtl_fw);
François Romieu953a12c2011-04-24 17:38:48 +02002393}
2394
2395static void rtl_apply_firmware_cond(struct rtl8169_private *tp, u8 reg, u16 val)
2396{
2397 if (rtl_readphy(tp, reg) != val)
2398 netif_warn(tp, hw, tp->dev, "chipset not ready for firmware\n");
2399 else
2400 rtl_apply_firmware(tp);
françois romieuf1e02ed2011-01-13 13:07:53 +00002401}
2402
françois romieu4da19632011-01-03 15:07:55 +00002403static void rtl8169s_hw_phy_config(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002405 static const struct phy_reg phy_reg_init[] = {
françois romieu0b9b5712009-08-10 19:44:56 +00002406 { 0x1f, 0x0001 },
2407 { 0x06, 0x006e },
2408 { 0x08, 0x0708 },
2409 { 0x15, 0x4000 },
2410 { 0x18, 0x65c7 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07002411
françois romieu0b9b5712009-08-10 19:44:56 +00002412 { 0x1f, 0x0001 },
2413 { 0x03, 0x00a1 },
2414 { 0x02, 0x0008 },
2415 { 0x01, 0x0120 },
2416 { 0x00, 0x1000 },
2417 { 0x04, 0x0800 },
2418 { 0x04, 0x0000 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07002419
françois romieu0b9b5712009-08-10 19:44:56 +00002420 { 0x03, 0xff41 },
2421 { 0x02, 0xdf60 },
2422 { 0x01, 0x0140 },
2423 { 0x00, 0x0077 },
2424 { 0x04, 0x7800 },
2425 { 0x04, 0x7000 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07002426
françois romieu0b9b5712009-08-10 19:44:56 +00002427 { 0x03, 0x802f },
2428 { 0x02, 0x4f02 },
2429 { 0x01, 0x0409 },
2430 { 0x00, 0xf0f9 },
2431 { 0x04, 0x9800 },
2432 { 0x04, 0x9000 },
2433
2434 { 0x03, 0xdf01 },
2435 { 0x02, 0xdf20 },
2436 { 0x01, 0xff95 },
2437 { 0x00, 0xba00 },
2438 { 0x04, 0xa800 },
2439 { 0x04, 0xa000 },
2440
2441 { 0x03, 0xff41 },
2442 { 0x02, 0xdf20 },
2443 { 0x01, 0x0140 },
2444 { 0x00, 0x00bb },
2445 { 0x04, 0xb800 },
2446 { 0x04, 0xb000 },
2447
2448 { 0x03, 0xdf41 },
2449 { 0x02, 0xdc60 },
2450 { 0x01, 0x6340 },
2451 { 0x00, 0x007d },
2452 { 0x04, 0xd800 },
2453 { 0x04, 0xd000 },
2454
2455 { 0x03, 0xdf01 },
2456 { 0x02, 0xdf20 },
2457 { 0x01, 0x100a },
2458 { 0x00, 0xa0ff },
2459 { 0x04, 0xf800 },
2460 { 0x04, 0xf000 },
2461
2462 { 0x1f, 0x0000 },
2463 { 0x0b, 0x0000 },
2464 { 0x00, 0x9200 }
2465 };
2466
françois romieu4da19632011-01-03 15:07:55 +00002467 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002468}
2469
françois romieu4da19632011-01-03 15:07:55 +00002470static void rtl8169sb_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu5615d9f2007-08-17 17:50:46 +02002471{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002472 static const struct phy_reg phy_reg_init[] = {
Francois Romieua441d7b2007-08-17 18:26:35 +02002473 { 0x1f, 0x0002 },
2474 { 0x01, 0x90d0 },
2475 { 0x1f, 0x0000 }
2476 };
2477
françois romieu4da19632011-01-03 15:07:55 +00002478 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu5615d9f2007-08-17 17:50:46 +02002479}
2480
françois romieu4da19632011-01-03 15:07:55 +00002481static void rtl8169scd_hw_phy_config_quirk(struct rtl8169_private *tp)
françois romieu2e9558562009-08-10 19:44:19 +00002482{
2483 struct pci_dev *pdev = tp->pci_dev;
françois romieu2e9558562009-08-10 19:44:19 +00002484
Sergei Shtylyovccbae552011-07-22 05:37:24 +00002485 if ((pdev->subsystem_vendor != PCI_VENDOR_ID_GIGABYTE) ||
2486 (pdev->subsystem_device != 0xe000))
françois romieu2e9558562009-08-10 19:44:19 +00002487 return;
2488
françois romieu4da19632011-01-03 15:07:55 +00002489 rtl_writephy(tp, 0x1f, 0x0001);
2490 rtl_writephy(tp, 0x10, 0xf01b);
2491 rtl_writephy(tp, 0x1f, 0x0000);
françois romieu2e9558562009-08-10 19:44:19 +00002492}
2493
françois romieu4da19632011-01-03 15:07:55 +00002494static void rtl8169scd_hw_phy_config(struct rtl8169_private *tp)
françois romieu2e9558562009-08-10 19:44:19 +00002495{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002496 static const struct phy_reg phy_reg_init[] = {
françois romieu2e9558562009-08-10 19:44:19 +00002497 { 0x1f, 0x0001 },
2498 { 0x04, 0x0000 },
2499 { 0x03, 0x00a1 },
2500 { 0x02, 0x0008 },
2501 { 0x01, 0x0120 },
2502 { 0x00, 0x1000 },
2503 { 0x04, 0x0800 },
2504 { 0x04, 0x9000 },
2505 { 0x03, 0x802f },
2506 { 0x02, 0x4f02 },
2507 { 0x01, 0x0409 },
2508 { 0x00, 0xf099 },
2509 { 0x04, 0x9800 },
2510 { 0x04, 0xa000 },
2511 { 0x03, 0xdf01 },
2512 { 0x02, 0xdf20 },
2513 { 0x01, 0xff95 },
2514 { 0x00, 0xba00 },
2515 { 0x04, 0xa800 },
2516 { 0x04, 0xf000 },
2517 { 0x03, 0xdf01 },
2518 { 0x02, 0xdf20 },
2519 { 0x01, 0x101a },
2520 { 0x00, 0xa0ff },
2521 { 0x04, 0xf800 },
2522 { 0x04, 0x0000 },
2523 { 0x1f, 0x0000 },
2524
2525 { 0x1f, 0x0001 },
2526 { 0x10, 0xf41b },
2527 { 0x14, 0xfb54 },
2528 { 0x18, 0xf5c7 },
2529 { 0x1f, 0x0000 },
2530
2531 { 0x1f, 0x0001 },
2532 { 0x17, 0x0cc0 },
2533 { 0x1f, 0x0000 }
2534 };
2535
françois romieu4da19632011-01-03 15:07:55 +00002536 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieu2e9558562009-08-10 19:44:19 +00002537
françois romieu4da19632011-01-03 15:07:55 +00002538 rtl8169scd_hw_phy_config_quirk(tp);
françois romieu2e9558562009-08-10 19:44:19 +00002539}
2540
françois romieu4da19632011-01-03 15:07:55 +00002541static void rtl8169sce_hw_phy_config(struct rtl8169_private *tp)
françois romieu8c7006a2009-08-10 19:43:29 +00002542{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002543 static const struct phy_reg phy_reg_init[] = {
françois romieu8c7006a2009-08-10 19:43:29 +00002544 { 0x1f, 0x0001 },
2545 { 0x04, 0x0000 },
2546 { 0x03, 0x00a1 },
2547 { 0x02, 0x0008 },
2548 { 0x01, 0x0120 },
2549 { 0x00, 0x1000 },
2550 { 0x04, 0x0800 },
2551 { 0x04, 0x9000 },
2552 { 0x03, 0x802f },
2553 { 0x02, 0x4f02 },
2554 { 0x01, 0x0409 },
2555 { 0x00, 0xf099 },
2556 { 0x04, 0x9800 },
2557 { 0x04, 0xa000 },
2558 { 0x03, 0xdf01 },
2559 { 0x02, 0xdf20 },
2560 { 0x01, 0xff95 },
2561 { 0x00, 0xba00 },
2562 { 0x04, 0xa800 },
2563 { 0x04, 0xf000 },
2564 { 0x03, 0xdf01 },
2565 { 0x02, 0xdf20 },
2566 { 0x01, 0x101a },
2567 { 0x00, 0xa0ff },
2568 { 0x04, 0xf800 },
2569 { 0x04, 0x0000 },
2570 { 0x1f, 0x0000 },
2571
2572 { 0x1f, 0x0001 },
2573 { 0x0b, 0x8480 },
2574 { 0x1f, 0x0000 },
2575
2576 { 0x1f, 0x0001 },
2577 { 0x18, 0x67c7 },
2578 { 0x04, 0x2000 },
2579 { 0x03, 0x002f },
2580 { 0x02, 0x4360 },
2581 { 0x01, 0x0109 },
2582 { 0x00, 0x3022 },
2583 { 0x04, 0x2800 },
2584 { 0x1f, 0x0000 },
2585
2586 { 0x1f, 0x0001 },
2587 { 0x17, 0x0cc0 },
2588 { 0x1f, 0x0000 }
2589 };
2590
françois romieu4da19632011-01-03 15:07:55 +00002591 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieu8c7006a2009-08-10 19:43:29 +00002592}
2593
françois romieu4da19632011-01-03 15:07:55 +00002594static void rtl8168bb_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu236b8082008-05-30 16:11:48 +02002595{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002596 static const struct phy_reg phy_reg_init[] = {
Francois Romieu236b8082008-05-30 16:11:48 +02002597 { 0x10, 0xf41b },
2598 { 0x1f, 0x0000 }
2599 };
2600
françois romieu4da19632011-01-03 15:07:55 +00002601 rtl_writephy(tp, 0x1f, 0x0001);
2602 rtl_patchphy(tp, 0x16, 1 << 0);
Francois Romieu236b8082008-05-30 16:11:48 +02002603
françois romieu4da19632011-01-03 15:07:55 +00002604 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu236b8082008-05-30 16:11:48 +02002605}
2606
françois romieu4da19632011-01-03 15:07:55 +00002607static void rtl8168bef_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu236b8082008-05-30 16:11:48 +02002608{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002609 static const struct phy_reg phy_reg_init[] = {
Francois Romieu236b8082008-05-30 16:11:48 +02002610 { 0x1f, 0x0001 },
2611 { 0x10, 0xf41b },
2612 { 0x1f, 0x0000 }
2613 };
2614
françois romieu4da19632011-01-03 15:07:55 +00002615 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu236b8082008-05-30 16:11:48 +02002616}
2617
françois romieu4da19632011-01-03 15:07:55 +00002618static void rtl8168cp_1_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu867763c2007-08-17 18:21:58 +02002619{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002620 static const struct phy_reg phy_reg_init[] = {
Francois Romieu867763c2007-08-17 18:21:58 +02002621 { 0x1f, 0x0000 },
2622 { 0x1d, 0x0f00 },
2623 { 0x1f, 0x0002 },
2624 { 0x0c, 0x1ec8 },
2625 { 0x1f, 0x0000 }
2626 };
2627
françois romieu4da19632011-01-03 15:07:55 +00002628 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu867763c2007-08-17 18:21:58 +02002629}
2630
françois romieu4da19632011-01-03 15:07:55 +00002631static void rtl8168cp_2_hw_phy_config(struct rtl8169_private *tp)
Francois Romieuef3386f2008-06-29 12:24:30 +02002632{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002633 static const struct phy_reg phy_reg_init[] = {
Francois Romieuef3386f2008-06-29 12:24:30 +02002634 { 0x1f, 0x0001 },
2635 { 0x1d, 0x3d98 },
2636 { 0x1f, 0x0000 }
2637 };
2638
françois romieu4da19632011-01-03 15:07:55 +00002639 rtl_writephy(tp, 0x1f, 0x0000);
2640 rtl_patchphy(tp, 0x14, 1 << 5);
2641 rtl_patchphy(tp, 0x0d, 1 << 5);
Francois Romieuef3386f2008-06-29 12:24:30 +02002642
françois romieu4da19632011-01-03 15:07:55 +00002643 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieuef3386f2008-06-29 12:24:30 +02002644}
2645
françois romieu4da19632011-01-03 15:07:55 +00002646static void rtl8168c_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 Romieua3f80672007-10-18 14:35:11 +02002649 { 0x1f, 0x0001 },
2650 { 0x12, 0x2300 },
Francois Romieu867763c2007-08-17 18:21:58 +02002651 { 0x1f, 0x0002 },
2652 { 0x00, 0x88d4 },
2653 { 0x01, 0x82b1 },
2654 { 0x03, 0x7002 },
2655 { 0x08, 0x9e30 },
2656 { 0x09, 0x01f0 },
2657 { 0x0a, 0x5500 },
2658 { 0x0c, 0x00c8 },
2659 { 0x1f, 0x0003 },
2660 { 0x12, 0xc096 },
2661 { 0x16, 0x000a },
Francois Romieuf50d4272008-05-30 16:07:07 +02002662 { 0x1f, 0x0000 },
2663 { 0x1f, 0x0000 },
2664 { 0x09, 0x2000 },
2665 { 0x09, 0x0000 }
Francois Romieu867763c2007-08-17 18:21:58 +02002666 };
2667
françois romieu4da19632011-01-03 15:07:55 +00002668 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieuf50d4272008-05-30 16:07:07 +02002669
françois romieu4da19632011-01-03 15:07:55 +00002670 rtl_patchphy(tp, 0x14, 1 << 5);
2671 rtl_patchphy(tp, 0x0d, 1 << 5);
2672 rtl_writephy(tp, 0x1f, 0x0000);
Francois Romieu867763c2007-08-17 18:21:58 +02002673}
2674
françois romieu4da19632011-01-03 15:07:55 +00002675static void rtl8168c_2_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu7da97ec2007-10-18 15:20:43 +02002676{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002677 static const struct phy_reg phy_reg_init[] = {
Francois Romieuf50d4272008-05-30 16:07:07 +02002678 { 0x1f, 0x0001 },
Francois Romieu7da97ec2007-10-18 15:20:43 +02002679 { 0x12, 0x2300 },
Francois Romieuf50d4272008-05-30 16:07:07 +02002680 { 0x03, 0x802f },
2681 { 0x02, 0x4f02 },
2682 { 0x01, 0x0409 },
2683 { 0x00, 0xf099 },
2684 { 0x04, 0x9800 },
2685 { 0x04, 0x9000 },
2686 { 0x1d, 0x3d98 },
Francois Romieu7da97ec2007-10-18 15:20:43 +02002687 { 0x1f, 0x0002 },
2688 { 0x0c, 0x7eb8 },
Francois Romieuf50d4272008-05-30 16:07:07 +02002689 { 0x06, 0x0761 },
2690 { 0x1f, 0x0003 },
2691 { 0x16, 0x0f0a },
Francois Romieu7da97ec2007-10-18 15:20:43 +02002692 { 0x1f, 0x0000 }
2693 };
2694
françois romieu4da19632011-01-03 15:07:55 +00002695 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieuf50d4272008-05-30 16:07:07 +02002696
françois romieu4da19632011-01-03 15:07:55 +00002697 rtl_patchphy(tp, 0x16, 1 << 0);
2698 rtl_patchphy(tp, 0x14, 1 << 5);
2699 rtl_patchphy(tp, 0x0d, 1 << 5);
2700 rtl_writephy(tp, 0x1f, 0x0000);
Francois Romieu7da97ec2007-10-18 15:20:43 +02002701}
2702
françois romieu4da19632011-01-03 15:07:55 +00002703static void rtl8168c_3_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu197ff762008-06-28 13:16:02 +02002704{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002705 static const struct phy_reg phy_reg_init[] = {
Francois Romieu197ff762008-06-28 13:16:02 +02002706 { 0x1f, 0x0001 },
2707 { 0x12, 0x2300 },
2708 { 0x1d, 0x3d98 },
2709 { 0x1f, 0x0002 },
2710 { 0x0c, 0x7eb8 },
2711 { 0x06, 0x5461 },
2712 { 0x1f, 0x0003 },
2713 { 0x16, 0x0f0a },
2714 { 0x1f, 0x0000 }
2715 };
2716
françois romieu4da19632011-01-03 15:07:55 +00002717 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu197ff762008-06-28 13:16:02 +02002718
françois romieu4da19632011-01-03 15:07:55 +00002719 rtl_patchphy(tp, 0x16, 1 << 0);
2720 rtl_patchphy(tp, 0x14, 1 << 5);
2721 rtl_patchphy(tp, 0x0d, 1 << 5);
2722 rtl_writephy(tp, 0x1f, 0x0000);
Francois Romieu197ff762008-06-28 13:16:02 +02002723}
2724
françois romieu4da19632011-01-03 15:07:55 +00002725static void rtl8168c_4_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu6fb07052008-06-29 11:54:28 +02002726{
françois romieu4da19632011-01-03 15:07:55 +00002727 rtl8168c_3_hw_phy_config(tp);
Francois Romieu6fb07052008-06-29 11:54:28 +02002728}
2729
françois romieubca03d52011-01-03 15:07:31 +00002730static void rtl8168d_1_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu5b538df2008-07-20 16:22:45 +02002731{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002732 static const struct phy_reg phy_reg_init_0[] = {
françois romieubca03d52011-01-03 15:07:31 +00002733 /* Channel Estimation */
Francois Romieu5b538df2008-07-20 16:22:45 +02002734 { 0x1f, 0x0001 },
françois romieudaf9df62009-10-07 12:44:20 +00002735 { 0x06, 0x4064 },
2736 { 0x07, 0x2863 },
2737 { 0x08, 0x059c },
2738 { 0x09, 0x26b4 },
2739 { 0x0a, 0x6a19 },
2740 { 0x0b, 0xdcc8 },
2741 { 0x10, 0xf06d },
2742 { 0x14, 0x7f68 },
2743 { 0x18, 0x7fd9 },
2744 { 0x1c, 0xf0ff },
2745 { 0x1d, 0x3d9c },
Francois Romieu5b538df2008-07-20 16:22:45 +02002746 { 0x1f, 0x0003 },
françois romieudaf9df62009-10-07 12:44:20 +00002747 { 0x12, 0xf49f },
2748 { 0x13, 0x070b },
2749 { 0x1a, 0x05ad },
françois romieubca03d52011-01-03 15:07:31 +00002750 { 0x14, 0x94c0 },
2751
2752 /*
2753 * Tx Error Issue
Francois Romieucecb5fd2011-04-01 10:21:07 +02002754 * Enhance line driver power
françois romieubca03d52011-01-03 15:07:31 +00002755 */
Francois Romieu5b538df2008-07-20 16:22:45 +02002756 { 0x1f, 0x0002 },
françois romieudaf9df62009-10-07 12:44:20 +00002757 { 0x06, 0x5561 },
Francois Romieu5b538df2008-07-20 16:22:45 +02002758 { 0x1f, 0x0005 },
françois romieudaf9df62009-10-07 12:44:20 +00002759 { 0x05, 0x8332 },
françois romieubca03d52011-01-03 15:07:31 +00002760 { 0x06, 0x5561 },
2761
2762 /*
2763 * Can not link to 1Gbps with bad cable
2764 * Decrease SNR threshold form 21.07dB to 19.04dB
2765 */
2766 { 0x1f, 0x0001 },
2767 { 0x17, 0x0cc0 },
françois romieudaf9df62009-10-07 12:44:20 +00002768
2769 { 0x1f, 0x0000 },
françois romieubca03d52011-01-03 15:07:31 +00002770 { 0x0d, 0xf880 }
Francois Romieu5b538df2008-07-20 16:22:45 +02002771 };
2772
françois romieu4da19632011-01-03 15:07:55 +00002773 rtl_writephy_batch(tp, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0));
Francois Romieu5b538df2008-07-20 16:22:45 +02002774
françois romieubca03d52011-01-03 15:07:31 +00002775 /*
2776 * Rx Error Issue
2777 * Fine Tune Switching regulator parameter
2778 */
françois romieu4da19632011-01-03 15:07:55 +00002779 rtl_writephy(tp, 0x1f, 0x0002);
2780 rtl_w1w0_phy(tp, 0x0b, 0x0010, 0x00ef);
2781 rtl_w1w0_phy(tp, 0x0c, 0xa200, 0x5d00);
françois romieudaf9df62009-10-07 12:44:20 +00002782
Francois Romieufdf6fc02012-07-06 22:40:38 +02002783 if (rtl8168d_efuse_read(tp, 0x01) == 0xb1) {
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002784 static const struct phy_reg phy_reg_init[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002785 { 0x1f, 0x0002 },
2786 { 0x05, 0x669a },
Francois Romieu5b538df2008-07-20 16:22:45 +02002787 { 0x1f, 0x0005 },
françois romieudaf9df62009-10-07 12:44:20 +00002788 { 0x05, 0x8330 },
2789 { 0x06, 0x669a },
2790 { 0x1f, 0x0002 }
2791 };
2792 int val;
2793
françois romieu4da19632011-01-03 15:07:55 +00002794 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieudaf9df62009-10-07 12:44:20 +00002795
françois romieu4da19632011-01-03 15:07:55 +00002796 val = rtl_readphy(tp, 0x0d);
françois romieudaf9df62009-10-07 12:44:20 +00002797
2798 if ((val & 0x00ff) != 0x006c) {
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002799 static const u32 set[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002800 0x0065, 0x0066, 0x0067, 0x0068,
2801 0x0069, 0x006a, 0x006b, 0x006c
2802 };
2803 int i;
2804
françois romieu4da19632011-01-03 15:07:55 +00002805 rtl_writephy(tp, 0x1f, 0x0002);
françois romieudaf9df62009-10-07 12:44:20 +00002806
2807 val &= 0xff00;
2808 for (i = 0; i < ARRAY_SIZE(set); i++)
françois romieu4da19632011-01-03 15:07:55 +00002809 rtl_writephy(tp, 0x0d, val | set[i]);
françois romieudaf9df62009-10-07 12:44:20 +00002810 }
2811 } else {
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, 0x6662 },
Francois Romieu5b538df2008-07-20 16:22:45 +02002815 { 0x1f, 0x0005 },
françois romieudaf9df62009-10-07 12:44:20 +00002816 { 0x05, 0x8330 },
2817 { 0x06, 0x6662 }
Francois Romieu5b538df2008-07-20 16:22:45 +02002818 };
2819
françois romieu4da19632011-01-03 15:07:55 +00002820 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu5b538df2008-07-20 16:22:45 +02002821 }
2822
françois romieubca03d52011-01-03 15:07:31 +00002823 /* RSET couple improve */
françois romieu4da19632011-01-03 15:07:55 +00002824 rtl_writephy(tp, 0x1f, 0x0002);
2825 rtl_patchphy(tp, 0x0d, 0x0300);
2826 rtl_patchphy(tp, 0x0f, 0x0010);
françois romieudaf9df62009-10-07 12:44:20 +00002827
françois romieubca03d52011-01-03 15:07:31 +00002828 /* Fine tune PLL performance */
françois romieu4da19632011-01-03 15:07:55 +00002829 rtl_writephy(tp, 0x1f, 0x0002);
2830 rtl_w1w0_phy(tp, 0x02, 0x0100, 0x0600);
2831 rtl_w1w0_phy(tp, 0x03, 0x0000, 0xe000);
françois romieudaf9df62009-10-07 12:44:20 +00002832
françois romieu4da19632011-01-03 15:07:55 +00002833 rtl_writephy(tp, 0x1f, 0x0005);
2834 rtl_writephy(tp, 0x05, 0x001b);
François Romieu953a12c2011-04-24 17:38:48 +02002835
2836 rtl_apply_firmware_cond(tp, MII_EXPANSION, 0xbf00);
françois romieubca03d52011-01-03 15:07:31 +00002837
françois romieu4da19632011-01-03 15:07:55 +00002838 rtl_writephy(tp, 0x1f, 0x0000);
françois romieudaf9df62009-10-07 12:44:20 +00002839}
2840
françois romieubca03d52011-01-03 15:07:31 +00002841static void rtl8168d_2_hw_phy_config(struct rtl8169_private *tp)
françois romieudaf9df62009-10-07 12:44:20 +00002842{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002843 static const struct phy_reg phy_reg_init_0[] = {
françois romieubca03d52011-01-03 15:07:31 +00002844 /* Channel Estimation */
françois romieudaf9df62009-10-07 12:44:20 +00002845 { 0x1f, 0x0001 },
2846 { 0x06, 0x4064 },
2847 { 0x07, 0x2863 },
2848 { 0x08, 0x059c },
2849 { 0x09, 0x26b4 },
2850 { 0x0a, 0x6a19 },
2851 { 0x0b, 0xdcc8 },
2852 { 0x10, 0xf06d },
2853 { 0x14, 0x7f68 },
2854 { 0x18, 0x7fd9 },
2855 { 0x1c, 0xf0ff },
2856 { 0x1d, 0x3d9c },
2857 { 0x1f, 0x0003 },
2858 { 0x12, 0xf49f },
2859 { 0x13, 0x070b },
2860 { 0x1a, 0x05ad },
2861 { 0x14, 0x94c0 },
2862
françois romieubca03d52011-01-03 15:07:31 +00002863 /*
2864 * Tx Error Issue
Francois Romieucecb5fd2011-04-01 10:21:07 +02002865 * Enhance line driver power
françois romieubca03d52011-01-03 15:07:31 +00002866 */
françois romieudaf9df62009-10-07 12:44:20 +00002867 { 0x1f, 0x0002 },
2868 { 0x06, 0x5561 },
2869 { 0x1f, 0x0005 },
2870 { 0x05, 0x8332 },
françois romieubca03d52011-01-03 15:07:31 +00002871 { 0x06, 0x5561 },
2872
2873 /*
2874 * Can not link to 1Gbps with bad cable
2875 * Decrease SNR threshold form 21.07dB to 19.04dB
2876 */
2877 { 0x1f, 0x0001 },
2878 { 0x17, 0x0cc0 },
françois romieudaf9df62009-10-07 12:44:20 +00002879
2880 { 0x1f, 0x0000 },
françois romieubca03d52011-01-03 15:07:31 +00002881 { 0x0d, 0xf880 }
françois romieudaf9df62009-10-07 12:44:20 +00002882 };
2883
françois romieu4da19632011-01-03 15:07:55 +00002884 rtl_writephy_batch(tp, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0));
françois romieudaf9df62009-10-07 12:44:20 +00002885
Francois Romieufdf6fc02012-07-06 22:40:38 +02002886 if (rtl8168d_efuse_read(tp, 0x01) == 0xb1) {
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002887 static const struct phy_reg phy_reg_init[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002888 { 0x1f, 0x0002 },
2889 { 0x05, 0x669a },
2890 { 0x1f, 0x0005 },
2891 { 0x05, 0x8330 },
2892 { 0x06, 0x669a },
2893
2894 { 0x1f, 0x0002 }
2895 };
2896 int val;
2897
françois romieu4da19632011-01-03 15:07:55 +00002898 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieudaf9df62009-10-07 12:44:20 +00002899
françois romieu4da19632011-01-03 15:07:55 +00002900 val = rtl_readphy(tp, 0x0d);
françois romieudaf9df62009-10-07 12:44:20 +00002901 if ((val & 0x00ff) != 0x006c) {
Joe Perchesb6bc7652010-12-21 02:16:08 -08002902 static const u32 set[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002903 0x0065, 0x0066, 0x0067, 0x0068,
2904 0x0069, 0x006a, 0x006b, 0x006c
2905 };
2906 int i;
2907
françois romieu4da19632011-01-03 15:07:55 +00002908 rtl_writephy(tp, 0x1f, 0x0002);
françois romieudaf9df62009-10-07 12:44:20 +00002909
2910 val &= 0xff00;
2911 for (i = 0; i < ARRAY_SIZE(set); i++)
françois romieu4da19632011-01-03 15:07:55 +00002912 rtl_writephy(tp, 0x0d, val | set[i]);
françois romieudaf9df62009-10-07 12:44:20 +00002913 }
2914 } else {
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, 0x2642 },
2918 { 0x1f, 0x0005 },
2919 { 0x05, 0x8330 },
2920 { 0x06, 0x2642 }
2921 };
2922
françois romieu4da19632011-01-03 15:07:55 +00002923 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieudaf9df62009-10-07 12:44:20 +00002924 }
2925
françois romieubca03d52011-01-03 15:07:31 +00002926 /* Fine tune PLL performance */
françois romieu4da19632011-01-03 15:07:55 +00002927 rtl_writephy(tp, 0x1f, 0x0002);
2928 rtl_w1w0_phy(tp, 0x02, 0x0100, 0x0600);
2929 rtl_w1w0_phy(tp, 0x03, 0x0000, 0xe000);
françois romieudaf9df62009-10-07 12:44:20 +00002930
françois romieubca03d52011-01-03 15:07:31 +00002931 /* Switching regulator Slew rate */
françois romieu4da19632011-01-03 15:07:55 +00002932 rtl_writephy(tp, 0x1f, 0x0002);
2933 rtl_patchphy(tp, 0x0f, 0x0017);
françois romieudaf9df62009-10-07 12:44:20 +00002934
françois romieu4da19632011-01-03 15:07:55 +00002935 rtl_writephy(tp, 0x1f, 0x0005);
2936 rtl_writephy(tp, 0x05, 0x001b);
François Romieu953a12c2011-04-24 17:38:48 +02002937
2938 rtl_apply_firmware_cond(tp, MII_EXPANSION, 0xb300);
françois romieubca03d52011-01-03 15:07:31 +00002939
françois romieu4da19632011-01-03 15:07:55 +00002940 rtl_writephy(tp, 0x1f, 0x0000);
françois romieudaf9df62009-10-07 12:44:20 +00002941}
2942
françois romieu4da19632011-01-03 15:07:55 +00002943static void rtl8168d_3_hw_phy_config(struct rtl8169_private *tp)
françois romieudaf9df62009-10-07 12:44:20 +00002944{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002945 static const struct phy_reg phy_reg_init[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002946 { 0x1f, 0x0002 },
2947 { 0x10, 0x0008 },
2948 { 0x0d, 0x006c },
2949
2950 { 0x1f, 0x0000 },
2951 { 0x0d, 0xf880 },
2952
2953 { 0x1f, 0x0001 },
2954 { 0x17, 0x0cc0 },
2955
2956 { 0x1f, 0x0001 },
2957 { 0x0b, 0xa4d8 },
2958 { 0x09, 0x281c },
2959 { 0x07, 0x2883 },
2960 { 0x0a, 0x6b35 },
2961 { 0x1d, 0x3da4 },
2962 { 0x1c, 0xeffd },
2963 { 0x14, 0x7f52 },
2964 { 0x18, 0x7fc6 },
2965 { 0x08, 0x0601 },
2966 { 0x06, 0x4063 },
2967 { 0x10, 0xf074 },
2968 { 0x1f, 0x0003 },
2969 { 0x13, 0x0789 },
2970 { 0x12, 0xf4bd },
2971 { 0x1a, 0x04fd },
2972 { 0x14, 0x84b0 },
2973 { 0x1f, 0x0000 },
2974 { 0x00, 0x9200 },
2975
2976 { 0x1f, 0x0005 },
2977 { 0x01, 0x0340 },
2978 { 0x1f, 0x0001 },
2979 { 0x04, 0x4000 },
2980 { 0x03, 0x1d21 },
2981 { 0x02, 0x0c32 },
2982 { 0x01, 0x0200 },
2983 { 0x00, 0x5554 },
2984 { 0x04, 0x4800 },
2985 { 0x04, 0x4000 },
2986 { 0x04, 0xf000 },
2987 { 0x03, 0xdf01 },
2988 { 0x02, 0xdf20 },
2989 { 0x01, 0x101a },
2990 { 0x00, 0xa0ff },
2991 { 0x04, 0xf800 },
2992 { 0x04, 0xf000 },
2993 { 0x1f, 0x0000 },
2994
2995 { 0x1f, 0x0007 },
2996 { 0x1e, 0x0023 },
2997 { 0x16, 0x0000 },
2998 { 0x1f, 0x0000 }
2999 };
3000
françois romieu4da19632011-01-03 15:07:55 +00003001 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu5b538df2008-07-20 16:22:45 +02003002}
3003
françois romieue6de30d2011-01-03 15:08:37 +00003004static void rtl8168d_4_hw_phy_config(struct rtl8169_private *tp)
3005{
3006 static const struct phy_reg phy_reg_init[] = {
3007 { 0x1f, 0x0001 },
3008 { 0x17, 0x0cc0 },
3009
3010 { 0x1f, 0x0007 },
3011 { 0x1e, 0x002d },
3012 { 0x18, 0x0040 },
3013 { 0x1f, 0x0000 }
3014 };
3015
3016 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3017 rtl_patchphy(tp, 0x0d, 1 << 5);
3018}
3019
Hayes Wang70090422011-07-06 15:58:06 +08003020static void rtl8168e_1_hw_phy_config(struct rtl8169_private *tp)
hayeswang01dc7fe2011-03-21 01:50:28 +00003021{
3022 static const struct phy_reg phy_reg_init[] = {
3023 /* Enable Delay cap */
3024 { 0x1f, 0x0005 },
3025 { 0x05, 0x8b80 },
3026 { 0x06, 0xc896 },
3027 { 0x1f, 0x0000 },
3028
3029 /* Channel estimation fine tune */
3030 { 0x1f, 0x0001 },
3031 { 0x0b, 0x6c20 },
3032 { 0x07, 0x2872 },
3033 { 0x1c, 0xefff },
3034 { 0x1f, 0x0003 },
3035 { 0x14, 0x6420 },
3036 { 0x1f, 0x0000 },
3037
3038 /* Update PFM & 10M TX idle timer */
3039 { 0x1f, 0x0007 },
3040 { 0x1e, 0x002f },
3041 { 0x15, 0x1919 },
3042 { 0x1f, 0x0000 },
3043
3044 { 0x1f, 0x0007 },
3045 { 0x1e, 0x00ac },
3046 { 0x18, 0x0006 },
3047 { 0x1f, 0x0000 }
3048 };
3049
Francois Romieu15ecd032011-04-27 13:52:22 -07003050 rtl_apply_firmware(tp);
3051
hayeswang01dc7fe2011-03-21 01:50:28 +00003052 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3053
3054 /* DCO enable for 10M IDLE Power */
3055 rtl_writephy(tp, 0x1f, 0x0007);
3056 rtl_writephy(tp, 0x1e, 0x0023);
3057 rtl_w1w0_phy(tp, 0x17, 0x0006, 0x0000);
3058 rtl_writephy(tp, 0x1f, 0x0000);
3059
3060 /* For impedance matching */
3061 rtl_writephy(tp, 0x1f, 0x0002);
3062 rtl_w1w0_phy(tp, 0x08, 0x8000, 0x7f00);
Francois Romieucecb5fd2011-04-01 10:21:07 +02003063 rtl_writephy(tp, 0x1f, 0x0000);
hayeswang01dc7fe2011-03-21 01:50:28 +00003064
3065 /* PHY auto speed down */
3066 rtl_writephy(tp, 0x1f, 0x0007);
3067 rtl_writephy(tp, 0x1e, 0x002d);
3068 rtl_w1w0_phy(tp, 0x18, 0x0050, 0x0000);
3069 rtl_writephy(tp, 0x1f, 0x0000);
3070 rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000);
3071
3072 rtl_writephy(tp, 0x1f, 0x0005);
3073 rtl_writephy(tp, 0x05, 0x8b86);
3074 rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000);
3075 rtl_writephy(tp, 0x1f, 0x0000);
3076
3077 rtl_writephy(tp, 0x1f, 0x0005);
3078 rtl_writephy(tp, 0x05, 0x8b85);
3079 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x2000);
3080 rtl_writephy(tp, 0x1f, 0x0007);
3081 rtl_writephy(tp, 0x1e, 0x0020);
3082 rtl_w1w0_phy(tp, 0x15, 0x0000, 0x1100);
3083 rtl_writephy(tp, 0x1f, 0x0006);
3084 rtl_writephy(tp, 0x00, 0x5a00);
3085 rtl_writephy(tp, 0x1f, 0x0000);
3086 rtl_writephy(tp, 0x0d, 0x0007);
3087 rtl_writephy(tp, 0x0e, 0x003c);
3088 rtl_writephy(tp, 0x0d, 0x4007);
3089 rtl_writephy(tp, 0x0e, 0x0000);
3090 rtl_writephy(tp, 0x0d, 0x0000);
3091}
3092
françois romieu9ecb9aa2012-12-07 11:20:21 +00003093static void rtl_rar_exgmac_set(struct rtl8169_private *tp, u8 *addr)
3094{
3095 const u16 w[] = {
3096 addr[0] | (addr[1] << 8),
3097 addr[2] | (addr[3] << 8),
3098 addr[4] | (addr[5] << 8)
3099 };
3100 const struct exgmac_reg e[] = {
3101 { .addr = 0xe0, ERIAR_MASK_1111, .val = w[0] | (w[1] << 16) },
3102 { .addr = 0xe4, ERIAR_MASK_1111, .val = w[2] },
3103 { .addr = 0xf0, ERIAR_MASK_1111, .val = w[0] << 16 },
3104 { .addr = 0xf4, ERIAR_MASK_1111, .val = w[1] | (w[2] << 16) }
3105 };
3106
3107 rtl_write_exgmac_batch(tp, e, ARRAY_SIZE(e));
3108}
3109
Hayes Wang70090422011-07-06 15:58:06 +08003110static void rtl8168e_2_hw_phy_config(struct rtl8169_private *tp)
3111{
3112 static const struct phy_reg phy_reg_init[] = {
3113 /* Enable Delay cap */
3114 { 0x1f, 0x0004 },
3115 { 0x1f, 0x0007 },
3116 { 0x1e, 0x00ac },
3117 { 0x18, 0x0006 },
3118 { 0x1f, 0x0002 },
3119 { 0x1f, 0x0000 },
3120 { 0x1f, 0x0000 },
3121
3122 /* Channel estimation fine tune */
3123 { 0x1f, 0x0003 },
3124 { 0x09, 0xa20f },
3125 { 0x1f, 0x0000 },
3126 { 0x1f, 0x0000 },
3127
3128 /* Green Setting */
3129 { 0x1f, 0x0005 },
3130 { 0x05, 0x8b5b },
3131 { 0x06, 0x9222 },
3132 { 0x05, 0x8b6d },
3133 { 0x06, 0x8000 },
3134 { 0x05, 0x8b76 },
3135 { 0x06, 0x8000 },
3136 { 0x1f, 0x0000 }
3137 };
3138
3139 rtl_apply_firmware(tp);
3140
3141 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3142
3143 /* For 4-corner performance improve */
3144 rtl_writephy(tp, 0x1f, 0x0005);
3145 rtl_writephy(tp, 0x05, 0x8b80);
3146 rtl_w1w0_phy(tp, 0x17, 0x0006, 0x0000);
3147 rtl_writephy(tp, 0x1f, 0x0000);
3148
3149 /* PHY auto speed down */
3150 rtl_writephy(tp, 0x1f, 0x0004);
3151 rtl_writephy(tp, 0x1f, 0x0007);
3152 rtl_writephy(tp, 0x1e, 0x002d);
3153 rtl_w1w0_phy(tp, 0x18, 0x0010, 0x0000);
3154 rtl_writephy(tp, 0x1f, 0x0002);
3155 rtl_writephy(tp, 0x1f, 0x0000);
3156 rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000);
3157
3158 /* improve 10M EEE waveform */
3159 rtl_writephy(tp, 0x1f, 0x0005);
3160 rtl_writephy(tp, 0x05, 0x8b86);
3161 rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000);
3162 rtl_writephy(tp, 0x1f, 0x0000);
3163
3164 /* Improve 2-pair detection performance */
3165 rtl_writephy(tp, 0x1f, 0x0005);
3166 rtl_writephy(tp, 0x05, 0x8b85);
3167 rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000);
3168 rtl_writephy(tp, 0x1f, 0x0000);
3169
3170 /* EEE setting */
Francois Romieufdf6fc02012-07-06 22:40:38 +02003171 rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_1111, 0x0000, 0x0003, ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08003172 rtl_writephy(tp, 0x1f, 0x0005);
3173 rtl_writephy(tp, 0x05, 0x8b85);
3174 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x2000);
3175 rtl_writephy(tp, 0x1f, 0x0004);
3176 rtl_writephy(tp, 0x1f, 0x0007);
3177 rtl_writephy(tp, 0x1e, 0x0020);
David S. Miller1805b2f2011-10-24 18:18:09 -04003178 rtl_w1w0_phy(tp, 0x15, 0x0000, 0x0100);
Hayes Wang70090422011-07-06 15:58:06 +08003179 rtl_writephy(tp, 0x1f, 0x0002);
3180 rtl_writephy(tp, 0x1f, 0x0000);
3181 rtl_writephy(tp, 0x0d, 0x0007);
3182 rtl_writephy(tp, 0x0e, 0x003c);
3183 rtl_writephy(tp, 0x0d, 0x4007);
3184 rtl_writephy(tp, 0x0e, 0x0000);
3185 rtl_writephy(tp, 0x0d, 0x0000);
3186
3187 /* Green feature */
3188 rtl_writephy(tp, 0x1f, 0x0003);
3189 rtl_w1w0_phy(tp, 0x19, 0x0000, 0x0001);
3190 rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0400);
3191 rtl_writephy(tp, 0x1f, 0x0000);
hayeswange0c07552012-10-23 20:24:03 +00003192
françois romieu9ecb9aa2012-12-07 11:20:21 +00003193 /* Broken BIOS workaround: feed GigaMAC registers with MAC address. */
3194 rtl_rar_exgmac_set(tp, tp->dev->dev_addr);
Hayes Wang70090422011-07-06 15:58:06 +08003195}
3196
Hayes Wang5f886e02012-03-30 14:33:03 +08003197static void rtl8168f_hw_phy_config(struct rtl8169_private *tp)
3198{
3199 /* For 4-corner performance improve */
3200 rtl_writephy(tp, 0x1f, 0x0005);
3201 rtl_writephy(tp, 0x05, 0x8b80);
3202 rtl_w1w0_phy(tp, 0x06, 0x0006, 0x0000);
3203 rtl_writephy(tp, 0x1f, 0x0000);
3204
3205 /* PHY auto speed down */
3206 rtl_writephy(tp, 0x1f, 0x0007);
3207 rtl_writephy(tp, 0x1e, 0x002d);
3208 rtl_w1w0_phy(tp, 0x18, 0x0010, 0x0000);
3209 rtl_writephy(tp, 0x1f, 0x0000);
3210 rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000);
3211
3212 /* Improve 10M EEE waveform */
3213 rtl_writephy(tp, 0x1f, 0x0005);
3214 rtl_writephy(tp, 0x05, 0x8b86);
3215 rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000);
3216 rtl_writephy(tp, 0x1f, 0x0000);
3217}
3218
Hayes Wangc2218922011-09-06 16:55:18 +08003219static void rtl8168f_1_hw_phy_config(struct rtl8169_private *tp)
3220{
3221 static const struct phy_reg phy_reg_init[] = {
3222 /* Channel estimation fine tune */
3223 { 0x1f, 0x0003 },
3224 { 0x09, 0xa20f },
3225 { 0x1f, 0x0000 },
3226
3227 /* Modify green table for giga & fnet */
3228 { 0x1f, 0x0005 },
3229 { 0x05, 0x8b55 },
3230 { 0x06, 0x0000 },
3231 { 0x05, 0x8b5e },
3232 { 0x06, 0x0000 },
3233 { 0x05, 0x8b67 },
3234 { 0x06, 0x0000 },
3235 { 0x05, 0x8b70 },
3236 { 0x06, 0x0000 },
3237 { 0x1f, 0x0000 },
3238 { 0x1f, 0x0007 },
3239 { 0x1e, 0x0078 },
3240 { 0x17, 0x0000 },
3241 { 0x19, 0x00fb },
3242 { 0x1f, 0x0000 },
3243
3244 /* Modify green table for 10M */
3245 { 0x1f, 0x0005 },
3246 { 0x05, 0x8b79 },
3247 { 0x06, 0xaa00 },
3248 { 0x1f, 0x0000 },
3249
3250 /* Disable hiimpedance detection (RTCT) */
3251 { 0x1f, 0x0003 },
3252 { 0x01, 0x328a },
3253 { 0x1f, 0x0000 }
3254 };
3255
3256 rtl_apply_firmware(tp);
3257
3258 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3259
Hayes Wang5f886e02012-03-30 14:33:03 +08003260 rtl8168f_hw_phy_config(tp);
Hayes Wangc2218922011-09-06 16:55:18 +08003261
3262 /* Improve 2-pair detection performance */
3263 rtl_writephy(tp, 0x1f, 0x0005);
3264 rtl_writephy(tp, 0x05, 0x8b85);
3265 rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000);
3266 rtl_writephy(tp, 0x1f, 0x0000);
3267}
3268
3269static void rtl8168f_2_hw_phy_config(struct rtl8169_private *tp)
3270{
3271 rtl_apply_firmware(tp);
3272
Hayes Wang5f886e02012-03-30 14:33:03 +08003273 rtl8168f_hw_phy_config(tp);
Hayes Wangc2218922011-09-06 16:55:18 +08003274}
3275
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003276static void rtl8411_hw_phy_config(struct rtl8169_private *tp)
3277{
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003278 static const struct phy_reg phy_reg_init[] = {
3279 /* Channel estimation fine tune */
3280 { 0x1f, 0x0003 },
3281 { 0x09, 0xa20f },
3282 { 0x1f, 0x0000 },
3283
3284 /* Modify green table for giga & fnet */
3285 { 0x1f, 0x0005 },
3286 { 0x05, 0x8b55 },
3287 { 0x06, 0x0000 },
3288 { 0x05, 0x8b5e },
3289 { 0x06, 0x0000 },
3290 { 0x05, 0x8b67 },
3291 { 0x06, 0x0000 },
3292 { 0x05, 0x8b70 },
3293 { 0x06, 0x0000 },
3294 { 0x1f, 0x0000 },
3295 { 0x1f, 0x0007 },
3296 { 0x1e, 0x0078 },
3297 { 0x17, 0x0000 },
3298 { 0x19, 0x00aa },
3299 { 0x1f, 0x0000 },
3300
3301 /* Modify green table for 10M */
3302 { 0x1f, 0x0005 },
3303 { 0x05, 0x8b79 },
3304 { 0x06, 0xaa00 },
3305 { 0x1f, 0x0000 },
3306
3307 /* Disable hiimpedance detection (RTCT) */
3308 { 0x1f, 0x0003 },
3309 { 0x01, 0x328a },
3310 { 0x1f, 0x0000 }
3311 };
3312
3313
3314 rtl_apply_firmware(tp);
3315
3316 rtl8168f_hw_phy_config(tp);
3317
3318 /* Improve 2-pair detection performance */
3319 rtl_writephy(tp, 0x1f, 0x0005);
3320 rtl_writephy(tp, 0x05, 0x8b85);
3321 rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000);
3322 rtl_writephy(tp, 0x1f, 0x0000);
3323
3324 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3325
3326 /* Modify green table for giga */
3327 rtl_writephy(tp, 0x1f, 0x0005);
3328 rtl_writephy(tp, 0x05, 0x8b54);
3329 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0800);
3330 rtl_writephy(tp, 0x05, 0x8b5d);
3331 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0800);
3332 rtl_writephy(tp, 0x05, 0x8a7c);
3333 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100);
3334 rtl_writephy(tp, 0x05, 0x8a7f);
3335 rtl_w1w0_phy(tp, 0x06, 0x0100, 0x0000);
3336 rtl_writephy(tp, 0x05, 0x8a82);
3337 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100);
3338 rtl_writephy(tp, 0x05, 0x8a85);
3339 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100);
3340 rtl_writephy(tp, 0x05, 0x8a88);
3341 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100);
3342 rtl_writephy(tp, 0x1f, 0x0000);
3343
3344 /* uc same-seed solution */
3345 rtl_writephy(tp, 0x1f, 0x0005);
3346 rtl_writephy(tp, 0x05, 0x8b85);
3347 rtl_w1w0_phy(tp, 0x06, 0x8000, 0x0000);
3348 rtl_writephy(tp, 0x1f, 0x0000);
3349
3350 /* eee setting */
Francois Romieufdf6fc02012-07-06 22:40:38 +02003351 rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_0001, 0x00, 0x03, ERIAR_EXGMAC);
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003352 rtl_writephy(tp, 0x1f, 0x0005);
3353 rtl_writephy(tp, 0x05, 0x8b85);
3354 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x2000);
3355 rtl_writephy(tp, 0x1f, 0x0004);
3356 rtl_writephy(tp, 0x1f, 0x0007);
3357 rtl_writephy(tp, 0x1e, 0x0020);
3358 rtl_w1w0_phy(tp, 0x15, 0x0000, 0x0100);
3359 rtl_writephy(tp, 0x1f, 0x0000);
3360 rtl_writephy(tp, 0x0d, 0x0007);
3361 rtl_writephy(tp, 0x0e, 0x003c);
3362 rtl_writephy(tp, 0x0d, 0x4007);
3363 rtl_writephy(tp, 0x0e, 0x0000);
3364 rtl_writephy(tp, 0x0d, 0x0000);
3365
3366 /* Green feature */
3367 rtl_writephy(tp, 0x1f, 0x0003);
3368 rtl_w1w0_phy(tp, 0x19, 0x0000, 0x0001);
3369 rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0400);
3370 rtl_writephy(tp, 0x1f, 0x0000);
3371}
3372
Hayes Wangc5583862012-07-02 17:23:22 +08003373static void rtl8168g_1_hw_phy_config(struct rtl8169_private *tp)
3374{
3375 static const u16 mac_ocp_patch[] = {
3376 0xe008, 0xe01b, 0xe01d, 0xe01f,
3377 0xe021, 0xe023, 0xe025, 0xe027,
3378 0x49d2, 0xf10d, 0x766c, 0x49e2,
3379 0xf00a, 0x1ec0, 0x8ee1, 0xc60a,
3380
3381 0x77c0, 0x4870, 0x9fc0, 0x1ea0,
3382 0xc707, 0x8ee1, 0x9d6c, 0xc603,
3383 0xbe00, 0xb416, 0x0076, 0xe86c,
3384 0xc602, 0xbe00, 0x0000, 0xc602,
3385
3386 0xbe00, 0x0000, 0xc602, 0xbe00,
3387 0x0000, 0xc602, 0xbe00, 0x0000,
3388 0xc602, 0xbe00, 0x0000, 0xc602,
3389 0xbe00, 0x0000, 0xc602, 0xbe00,
3390
3391 0x0000, 0x0000, 0x0000, 0x0000
3392 };
3393 u32 i;
3394
3395 /* Patch code for GPHY reset */
3396 for (i = 0; i < ARRAY_SIZE(mac_ocp_patch); i++)
3397 r8168_mac_ocp_write(tp, 0xf800 + 2*i, mac_ocp_patch[i]);
3398 r8168_mac_ocp_write(tp, 0xfc26, 0x8000);
3399 r8168_mac_ocp_write(tp, 0xfc28, 0x0075);
3400
3401 rtl_apply_firmware(tp);
3402
3403 if (r8168_phy_ocp_read(tp, 0xa460) & 0x0100)
3404 rtl_w1w0_phy_ocp(tp, 0xbcc4, 0x0000, 0x8000);
3405 else
3406 rtl_w1w0_phy_ocp(tp, 0xbcc4, 0x8000, 0x0000);
3407
3408 if (r8168_phy_ocp_read(tp, 0xa466) & 0x0100)
3409 rtl_w1w0_phy_ocp(tp, 0xc41a, 0x0002, 0x0000);
3410 else
3411 rtl_w1w0_phy_ocp(tp, 0xbcc4, 0x0000, 0x0002);
3412
3413 rtl_w1w0_phy_ocp(tp, 0xa442, 0x000c, 0x0000);
3414 rtl_w1w0_phy_ocp(tp, 0xa4b2, 0x0004, 0x0000);
3415
3416 r8168_phy_ocp_write(tp, 0xa436, 0x8012);
3417 rtl_w1w0_phy_ocp(tp, 0xa438, 0x8000, 0x0000);
3418
3419 rtl_w1w0_phy_ocp(tp, 0xc422, 0x4000, 0x2000);
3420}
3421
françois romieu4da19632011-01-03 15:07:55 +00003422static void rtl8102e_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu2857ffb2008-08-02 21:08:49 +02003423{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08003424 static const struct phy_reg phy_reg_init[] = {
Francois Romieu2857ffb2008-08-02 21:08:49 +02003425 { 0x1f, 0x0003 },
3426 { 0x08, 0x441d },
3427 { 0x01, 0x9100 },
3428 { 0x1f, 0x0000 }
3429 };
3430
françois romieu4da19632011-01-03 15:07:55 +00003431 rtl_writephy(tp, 0x1f, 0x0000);
3432 rtl_patchphy(tp, 0x11, 1 << 12);
3433 rtl_patchphy(tp, 0x19, 1 << 13);
3434 rtl_patchphy(tp, 0x10, 1 << 15);
Francois Romieu2857ffb2008-08-02 21:08:49 +02003435
françois romieu4da19632011-01-03 15:07:55 +00003436 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu2857ffb2008-08-02 21:08:49 +02003437}
3438
Hayes Wang5a5e4442011-02-22 17:26:21 +08003439static void rtl8105e_hw_phy_config(struct rtl8169_private *tp)
3440{
3441 static const struct phy_reg phy_reg_init[] = {
3442 { 0x1f, 0x0005 },
3443 { 0x1a, 0x0000 },
3444 { 0x1f, 0x0000 },
3445
3446 { 0x1f, 0x0004 },
3447 { 0x1c, 0x0000 },
3448 { 0x1f, 0x0000 },
3449
3450 { 0x1f, 0x0001 },
3451 { 0x15, 0x7701 },
3452 { 0x1f, 0x0000 }
3453 };
3454
3455 /* Disable ALDPS before ram code */
Francois Romieueef63cc2013-02-08 23:43:20 +01003456 rtl_writephy(tp, 0x1f, 0x0000);
3457 rtl_writephy(tp, 0x18, 0x0310);
3458 msleep(100);
Hayes Wang5a5e4442011-02-22 17:26:21 +08003459
François Romieu953a12c2011-04-24 17:38:48 +02003460 rtl_apply_firmware(tp);
Hayes Wang5a5e4442011-02-22 17:26:21 +08003461
3462 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3463}
3464
Hayes Wang7e18dca2012-03-30 14:33:02 +08003465static void rtl8402_hw_phy_config(struct rtl8169_private *tp)
3466{
Hayes Wang7e18dca2012-03-30 14:33:02 +08003467 /* Disable ALDPS before setting firmware */
Francois Romieueef63cc2013-02-08 23:43:20 +01003468 rtl_writephy(tp, 0x1f, 0x0000);
3469 rtl_writephy(tp, 0x18, 0x0310);
3470 msleep(20);
Hayes Wang7e18dca2012-03-30 14:33:02 +08003471
3472 rtl_apply_firmware(tp);
3473
3474 /* EEE setting */
Francois Romieufdf6fc02012-07-06 22:40:38 +02003475 rtl_eri_write(tp, 0x1b0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
Hayes Wang7e18dca2012-03-30 14:33:02 +08003476 rtl_writephy(tp, 0x1f, 0x0004);
3477 rtl_writephy(tp, 0x10, 0x401f);
3478 rtl_writephy(tp, 0x19, 0x7030);
3479 rtl_writephy(tp, 0x1f, 0x0000);
3480}
3481
Hayes Wang5598bfe2012-07-02 17:23:21 +08003482static void rtl8106e_hw_phy_config(struct rtl8169_private *tp)
3483{
Hayes Wang5598bfe2012-07-02 17:23:21 +08003484 static const struct phy_reg phy_reg_init[] = {
3485 { 0x1f, 0x0004 },
3486 { 0x10, 0xc07f },
3487 { 0x19, 0x7030 },
3488 { 0x1f, 0x0000 }
3489 };
3490
3491 /* Disable ALDPS before ram code */
Francois Romieueef63cc2013-02-08 23:43:20 +01003492 rtl_writephy(tp, 0x1f, 0x0000);
3493 rtl_writephy(tp, 0x18, 0x0310);
3494 msleep(100);
Hayes Wang5598bfe2012-07-02 17:23:21 +08003495
3496 rtl_apply_firmware(tp);
3497
Francois Romieufdf6fc02012-07-06 22:40:38 +02003498 rtl_eri_write(tp, 0x1b0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
Hayes Wang5598bfe2012-07-02 17:23:21 +08003499 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3500
Francois Romieufdf6fc02012-07-06 22:40:38 +02003501 rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
Hayes Wang5598bfe2012-07-02 17:23:21 +08003502}
3503
Francois Romieu5615d9f2007-08-17 17:50:46 +02003504static void rtl_hw_phy_config(struct net_device *dev)
3505{
3506 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieu5615d9f2007-08-17 17:50:46 +02003507
3508 rtl8169_print_mac_version(tp);
3509
3510 switch (tp->mac_version) {
3511 case RTL_GIGA_MAC_VER_01:
3512 break;
3513 case RTL_GIGA_MAC_VER_02:
3514 case RTL_GIGA_MAC_VER_03:
françois romieu4da19632011-01-03 15:07:55 +00003515 rtl8169s_hw_phy_config(tp);
Francois Romieu5615d9f2007-08-17 17:50:46 +02003516 break;
3517 case RTL_GIGA_MAC_VER_04:
françois romieu4da19632011-01-03 15:07:55 +00003518 rtl8169sb_hw_phy_config(tp);
Francois Romieu5615d9f2007-08-17 17:50:46 +02003519 break;
françois romieu2e9558562009-08-10 19:44:19 +00003520 case RTL_GIGA_MAC_VER_05:
françois romieu4da19632011-01-03 15:07:55 +00003521 rtl8169scd_hw_phy_config(tp);
françois romieu2e9558562009-08-10 19:44:19 +00003522 break;
françois romieu8c7006a2009-08-10 19:43:29 +00003523 case RTL_GIGA_MAC_VER_06:
françois romieu4da19632011-01-03 15:07:55 +00003524 rtl8169sce_hw_phy_config(tp);
françois romieu8c7006a2009-08-10 19:43:29 +00003525 break;
Francois Romieu2857ffb2008-08-02 21:08:49 +02003526 case RTL_GIGA_MAC_VER_07:
3527 case RTL_GIGA_MAC_VER_08:
3528 case RTL_GIGA_MAC_VER_09:
françois romieu4da19632011-01-03 15:07:55 +00003529 rtl8102e_hw_phy_config(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02003530 break;
Francois Romieu236b8082008-05-30 16:11:48 +02003531 case RTL_GIGA_MAC_VER_11:
françois romieu4da19632011-01-03 15:07:55 +00003532 rtl8168bb_hw_phy_config(tp);
Francois Romieu236b8082008-05-30 16:11:48 +02003533 break;
3534 case RTL_GIGA_MAC_VER_12:
françois romieu4da19632011-01-03 15:07:55 +00003535 rtl8168bef_hw_phy_config(tp);
Francois Romieu236b8082008-05-30 16:11:48 +02003536 break;
3537 case RTL_GIGA_MAC_VER_17:
françois romieu4da19632011-01-03 15:07:55 +00003538 rtl8168bef_hw_phy_config(tp);
Francois Romieu236b8082008-05-30 16:11:48 +02003539 break;
Francois Romieu867763c2007-08-17 18:21:58 +02003540 case RTL_GIGA_MAC_VER_18:
françois romieu4da19632011-01-03 15:07:55 +00003541 rtl8168cp_1_hw_phy_config(tp);
Francois Romieu867763c2007-08-17 18:21:58 +02003542 break;
3543 case RTL_GIGA_MAC_VER_19:
françois romieu4da19632011-01-03 15:07:55 +00003544 rtl8168c_1_hw_phy_config(tp);
Francois Romieu867763c2007-08-17 18:21:58 +02003545 break;
Francois Romieu7da97ec2007-10-18 15:20:43 +02003546 case RTL_GIGA_MAC_VER_20:
françois romieu4da19632011-01-03 15:07:55 +00003547 rtl8168c_2_hw_phy_config(tp);
Francois Romieu7da97ec2007-10-18 15:20:43 +02003548 break;
Francois Romieu197ff762008-06-28 13:16:02 +02003549 case RTL_GIGA_MAC_VER_21:
françois romieu4da19632011-01-03 15:07:55 +00003550 rtl8168c_3_hw_phy_config(tp);
Francois Romieu197ff762008-06-28 13:16:02 +02003551 break;
Francois Romieu6fb07052008-06-29 11:54:28 +02003552 case RTL_GIGA_MAC_VER_22:
françois romieu4da19632011-01-03 15:07:55 +00003553 rtl8168c_4_hw_phy_config(tp);
Francois Romieu6fb07052008-06-29 11:54:28 +02003554 break;
Francois Romieuef3386f2008-06-29 12:24:30 +02003555 case RTL_GIGA_MAC_VER_23:
Francois Romieu7f3e3d32008-07-20 18:53:20 +02003556 case RTL_GIGA_MAC_VER_24:
françois romieu4da19632011-01-03 15:07:55 +00003557 rtl8168cp_2_hw_phy_config(tp);
Francois Romieuef3386f2008-06-29 12:24:30 +02003558 break;
Francois Romieu5b538df2008-07-20 16:22:45 +02003559 case RTL_GIGA_MAC_VER_25:
françois romieubca03d52011-01-03 15:07:31 +00003560 rtl8168d_1_hw_phy_config(tp);
françois romieudaf9df62009-10-07 12:44:20 +00003561 break;
3562 case RTL_GIGA_MAC_VER_26:
françois romieubca03d52011-01-03 15:07:31 +00003563 rtl8168d_2_hw_phy_config(tp);
françois romieudaf9df62009-10-07 12:44:20 +00003564 break;
3565 case RTL_GIGA_MAC_VER_27:
françois romieu4da19632011-01-03 15:07:55 +00003566 rtl8168d_3_hw_phy_config(tp);
Francois Romieu5b538df2008-07-20 16:22:45 +02003567 break;
françois romieue6de30d2011-01-03 15:08:37 +00003568 case RTL_GIGA_MAC_VER_28:
3569 rtl8168d_4_hw_phy_config(tp);
3570 break;
Hayes Wang5a5e4442011-02-22 17:26:21 +08003571 case RTL_GIGA_MAC_VER_29:
3572 case RTL_GIGA_MAC_VER_30:
3573 rtl8105e_hw_phy_config(tp);
3574 break;
Francois Romieucecb5fd2011-04-01 10:21:07 +02003575 case RTL_GIGA_MAC_VER_31:
3576 /* None. */
3577 break;
hayeswang01dc7fe2011-03-21 01:50:28 +00003578 case RTL_GIGA_MAC_VER_32:
hayeswang01dc7fe2011-03-21 01:50:28 +00003579 case RTL_GIGA_MAC_VER_33:
Hayes Wang70090422011-07-06 15:58:06 +08003580 rtl8168e_1_hw_phy_config(tp);
3581 break;
3582 case RTL_GIGA_MAC_VER_34:
3583 rtl8168e_2_hw_phy_config(tp);
hayeswang01dc7fe2011-03-21 01:50:28 +00003584 break;
Hayes Wangc2218922011-09-06 16:55:18 +08003585 case RTL_GIGA_MAC_VER_35:
3586 rtl8168f_1_hw_phy_config(tp);
3587 break;
3588 case RTL_GIGA_MAC_VER_36:
3589 rtl8168f_2_hw_phy_config(tp);
3590 break;
Francois Romieuef3386f2008-06-29 12:24:30 +02003591
Hayes Wang7e18dca2012-03-30 14:33:02 +08003592 case RTL_GIGA_MAC_VER_37:
3593 rtl8402_hw_phy_config(tp);
3594 break;
3595
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003596 case RTL_GIGA_MAC_VER_38:
3597 rtl8411_hw_phy_config(tp);
3598 break;
3599
Hayes Wang5598bfe2012-07-02 17:23:21 +08003600 case RTL_GIGA_MAC_VER_39:
3601 rtl8106e_hw_phy_config(tp);
3602 break;
3603
Hayes Wangc5583862012-07-02 17:23:22 +08003604 case RTL_GIGA_MAC_VER_40:
3605 rtl8168g_1_hw_phy_config(tp);
3606 break;
3607
3608 case RTL_GIGA_MAC_VER_41:
Francois Romieu5615d9f2007-08-17 17:50:46 +02003609 default:
3610 break;
3611 }
3612}
3613
Francois Romieuda78dbf2012-01-26 14:18:23 +01003614static void rtl_phy_work(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003615{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003616 struct timer_list *timer = &tp->timer;
3617 void __iomem *ioaddr = tp->mmio_addr;
3618 unsigned long timeout = RTL8169_PHY_TIMEOUT;
3619
Francois Romieubcf0bf92006-07-26 23:14:13 +02003620 assert(tp->mac_version > RTL_GIGA_MAC_VER_01);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003621
françois romieu4da19632011-01-03 15:07:55 +00003622 if (tp->phy_reset_pending(tp)) {
Francois Romieu5b0384f2006-08-16 16:00:01 +02003623 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07003624 * A busy loop could burn quite a few cycles on nowadays CPU.
3625 * Let's delay the execution of the timer for a few ticks.
3626 */
3627 timeout = HZ/10;
3628 goto out_mod_timer;
3629 }
3630
3631 if (tp->link_ok(ioaddr))
Francois Romieuda78dbf2012-01-26 14:18:23 +01003632 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003633
Francois Romieuda78dbf2012-01-26 14:18:23 +01003634 netif_warn(tp, link, tp->dev, "PHY reset until link up\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003635
françois romieu4da19632011-01-03 15:07:55 +00003636 tp->phy_reset_enable(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003637
3638out_mod_timer:
3639 mod_timer(timer, jiffies + timeout);
Francois Romieuda78dbf2012-01-26 14:18:23 +01003640}
3641
3642static void rtl_schedule_task(struct rtl8169_private *tp, enum rtl_flag flag)
3643{
Francois Romieuda78dbf2012-01-26 14:18:23 +01003644 if (!test_and_set_bit(flag, tp->wk.flags))
3645 schedule_work(&tp->wk.work);
Francois Romieuda78dbf2012-01-26 14:18:23 +01003646}
3647
3648static void rtl8169_phy_timer(unsigned long __opaque)
3649{
3650 struct net_device *dev = (struct net_device *)__opaque;
3651 struct rtl8169_private *tp = netdev_priv(dev);
3652
Francois Romieu98ddf982012-01-31 10:47:34 +01003653 rtl_schedule_task(tp, RTL_FLAG_TASK_PHY_PENDING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003654}
3655
Linus Torvalds1da177e2005-04-16 15:20:36 -07003656static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev,
3657 void __iomem *ioaddr)
3658{
3659 iounmap(ioaddr);
3660 pci_release_regions(pdev);
françois romieu87aeec72010-04-26 11:42:06 +00003661 pci_clear_mwi(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003662 pci_disable_device(pdev);
3663 free_netdev(dev);
3664}
3665
Francois Romieuffc46952012-07-06 14:19:23 +02003666DECLARE_RTL_COND(rtl_phy_reset_cond)
3667{
3668 return tp->phy_reset_pending(tp);
3669}
3670
Francois Romieubf793292006-11-01 00:53:05 +01003671static void rtl8169_phy_reset(struct net_device *dev,
3672 struct rtl8169_private *tp)
3673{
françois romieu4da19632011-01-03 15:07:55 +00003674 tp->phy_reset_enable(tp);
Francois Romieuffc46952012-07-06 14:19:23 +02003675 rtl_msleep_loop_wait_low(tp, &rtl_phy_reset_cond, 1, 100);
Francois Romieubf793292006-11-01 00:53:05 +01003676}
3677
David S. Miller8decf862011-09-22 03:23:13 -04003678static bool rtl_tbi_enabled(struct rtl8169_private *tp)
3679{
3680 void __iomem *ioaddr = tp->mmio_addr;
3681
3682 return (tp->mac_version == RTL_GIGA_MAC_VER_01) &&
3683 (RTL_R8(PHYstatus) & TBI_Enable);
3684}
3685
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003686static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003687{
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003688 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003689
Francois Romieu5615d9f2007-08-17 17:50:46 +02003690 rtl_hw_phy_config(dev);
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003691
Marcus Sundberg773328942008-07-10 21:28:08 +02003692 if (tp->mac_version <= RTL_GIGA_MAC_VER_06) {
3693 dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
3694 RTL_W8(0x82, 0x01);
3695 }
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003696
Francois Romieu6dccd162007-02-13 23:38:05 +01003697 pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40);
3698
3699 if (tp->mac_version <= RTL_GIGA_MAC_VER_06)
3700 pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08);
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003701
Francois Romieubcf0bf92006-07-26 23:14:13 +02003702 if (tp->mac_version == RTL_GIGA_MAC_VER_02) {
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003703 dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
3704 RTL_W8(0x82, 0x01);
3705 dprintk("Set PHY Reg 0x0bh = 0x00h\n");
françois romieu4da19632011-01-03 15:07:55 +00003706 rtl_writephy(tp, 0x0b, 0x0000); //w 0x0b 15 0 0
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003707 }
3708
Francois Romieubf793292006-11-01 00:53:05 +01003709 rtl8169_phy_reset(dev, tp);
3710
Oliver Neukum54405cd2011-01-06 21:55:13 +01003711 rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL,
Francois Romieucecb5fd2011-04-01 10:21:07 +02003712 ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
3713 ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |
3714 (tp->mii.supports_gmii ?
3715 ADVERTISED_1000baseT_Half |
3716 ADVERTISED_1000baseT_Full : 0));
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003717
David S. Miller8decf862011-09-22 03:23:13 -04003718 if (rtl_tbi_enabled(tp))
Joe Perchesbf82c182010-02-09 11:49:50 +00003719 netif_info(tp, link, dev, "TBI auto-negotiating\n");
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003720}
3721
Francois Romieu773d2022007-01-31 23:47:43 +01003722static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr)
3723{
3724 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu773d2022007-01-31 23:47:43 +01003725
Francois Romieuda78dbf2012-01-26 14:18:23 +01003726 rtl_lock_work(tp);
Francois Romieu773d2022007-01-31 23:47:43 +01003727
3728 RTL_W8(Cfg9346, Cfg9346_Unlock);
françois romieu908ba2b2010-04-26 11:42:58 +00003729
françois romieu9ecb9aa2012-12-07 11:20:21 +00003730 RTL_W32(MAC4, addr[4] | addr[5] << 8);
françois romieu908ba2b2010-04-26 11:42:58 +00003731 RTL_R32(MAC4);
3732
françois romieu9ecb9aa2012-12-07 11:20:21 +00003733 RTL_W32(MAC0, addr[0] | addr[1] << 8 | addr[2] << 16 | addr[3] << 24);
françois romieu908ba2b2010-04-26 11:42:58 +00003734 RTL_R32(MAC0);
3735
françois romieu9ecb9aa2012-12-07 11:20:21 +00003736 if (tp->mac_version == RTL_GIGA_MAC_VER_34)
3737 rtl_rar_exgmac_set(tp, addr);
françois romieuc28aa382011-08-02 03:53:43 +00003738
Francois Romieu773d2022007-01-31 23:47:43 +01003739 RTL_W8(Cfg9346, Cfg9346_Lock);
3740
Francois Romieuda78dbf2012-01-26 14:18:23 +01003741 rtl_unlock_work(tp);
Francois Romieu773d2022007-01-31 23:47:43 +01003742}
3743
3744static int rtl_set_mac_address(struct net_device *dev, void *p)
3745{
3746 struct rtl8169_private *tp = netdev_priv(dev);
3747 struct sockaddr *addr = p;
3748
3749 if (!is_valid_ether_addr(addr->sa_data))
3750 return -EADDRNOTAVAIL;
3751
3752 memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
3753
3754 rtl_rar_set(tp, dev->dev_addr);
3755
3756 return 0;
3757}
3758
Francois Romieu5f787a12006-08-17 13:02:36 +02003759static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
3760{
3761 struct rtl8169_private *tp = netdev_priv(dev);
3762 struct mii_ioctl_data *data = if_mii(ifr);
3763
Francois Romieu8b4ab282008-11-19 22:05:25 -08003764 return netif_running(dev) ? tp->do_ioctl(tp, data, cmd) : -ENODEV;
3765}
Francois Romieu5f787a12006-08-17 13:02:36 +02003766
Francois Romieucecb5fd2011-04-01 10:21:07 +02003767static int rtl_xmii_ioctl(struct rtl8169_private *tp,
3768 struct mii_ioctl_data *data, int cmd)
Francois Romieu8b4ab282008-11-19 22:05:25 -08003769{
Francois Romieu5f787a12006-08-17 13:02:36 +02003770 switch (cmd) {
3771 case SIOCGMIIPHY:
3772 data->phy_id = 32; /* Internal PHY */
3773 return 0;
3774
3775 case SIOCGMIIREG:
françois romieu4da19632011-01-03 15:07:55 +00003776 data->val_out = rtl_readphy(tp, data->reg_num & 0x1f);
Francois Romieu5f787a12006-08-17 13:02:36 +02003777 return 0;
3778
3779 case SIOCSMIIREG:
françois romieu4da19632011-01-03 15:07:55 +00003780 rtl_writephy(tp, data->reg_num & 0x1f, data->val_in);
Francois Romieu5f787a12006-08-17 13:02:36 +02003781 return 0;
3782 }
3783 return -EOPNOTSUPP;
3784}
3785
Francois Romieu8b4ab282008-11-19 22:05:25 -08003786static int rtl_tbi_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd)
3787{
3788 return -EOPNOTSUPP;
3789}
3790
Francois Romieufbac58f2007-10-04 22:51:38 +02003791static void rtl_disable_msi(struct pci_dev *pdev, struct rtl8169_private *tp)
3792{
3793 if (tp->features & RTL_FEATURE_MSI) {
3794 pci_disable_msi(pdev);
3795 tp->features &= ~RTL_FEATURE_MSI;
3796 }
3797}
3798
Bill Pembertonbaf63292012-12-03 09:23:28 -05003799static void rtl_init_mdio_ops(struct rtl8169_private *tp)
françois romieuc0e45c12011-01-03 15:08:04 +00003800{
3801 struct mdio_ops *ops = &tp->mdio_ops;
3802
3803 switch (tp->mac_version) {
3804 case RTL_GIGA_MAC_VER_27:
3805 ops->write = r8168dp_1_mdio_write;
3806 ops->read = r8168dp_1_mdio_read;
3807 break;
françois romieue6de30d2011-01-03 15:08:37 +00003808 case RTL_GIGA_MAC_VER_28:
hayeswang4804b3b2011-03-21 01:50:29 +00003809 case RTL_GIGA_MAC_VER_31:
françois romieue6de30d2011-01-03 15:08:37 +00003810 ops->write = r8168dp_2_mdio_write;
3811 ops->read = r8168dp_2_mdio_read;
3812 break;
Hayes Wangc5583862012-07-02 17:23:22 +08003813 case RTL_GIGA_MAC_VER_40:
3814 case RTL_GIGA_MAC_VER_41:
3815 ops->write = r8168g_mdio_write;
3816 ops->read = r8168g_mdio_read;
3817 break;
françois romieuc0e45c12011-01-03 15:08:04 +00003818 default:
3819 ops->write = r8169_mdio_write;
3820 ops->read = r8169_mdio_read;
3821 break;
3822 }
3823}
3824
David S. Miller1805b2f2011-10-24 18:18:09 -04003825static void rtl_wol_suspend_quirk(struct rtl8169_private *tp)
3826{
3827 void __iomem *ioaddr = tp->mmio_addr;
3828
3829 switch (tp->mac_version) {
Cyril Bruleboisb00e69d2012-10-31 14:00:46 +00003830 case RTL_GIGA_MAC_VER_25:
3831 case RTL_GIGA_MAC_VER_26:
David S. Miller1805b2f2011-10-24 18:18:09 -04003832 case RTL_GIGA_MAC_VER_29:
3833 case RTL_GIGA_MAC_VER_30:
3834 case RTL_GIGA_MAC_VER_32:
3835 case RTL_GIGA_MAC_VER_33:
3836 case RTL_GIGA_MAC_VER_34:
Hayes Wang7e18dca2012-03-30 14:33:02 +08003837 case RTL_GIGA_MAC_VER_37:
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003838 case RTL_GIGA_MAC_VER_38:
Hayes Wang5598bfe2012-07-02 17:23:21 +08003839 case RTL_GIGA_MAC_VER_39:
Hayes Wangc5583862012-07-02 17:23:22 +08003840 case RTL_GIGA_MAC_VER_40:
3841 case RTL_GIGA_MAC_VER_41:
David S. Miller1805b2f2011-10-24 18:18:09 -04003842 RTL_W32(RxConfig, RTL_R32(RxConfig) |
3843 AcceptBroadcast | AcceptMulticast | AcceptMyPhys);
3844 break;
3845 default:
3846 break;
3847 }
3848}
3849
3850static bool rtl_wol_pll_power_down(struct rtl8169_private *tp)
3851{
3852 if (!(__rtl8169_get_wol(tp) & WAKE_ANY))
3853 return false;
3854
3855 rtl_writephy(tp, 0x1f, 0x0000);
3856 rtl_writephy(tp, MII_BMCR, 0x0000);
3857
3858 rtl_wol_suspend_quirk(tp);
3859
3860 return true;
3861}
3862
françois romieu065c27c2011-01-03 15:08:12 +00003863static void r810x_phy_power_down(struct rtl8169_private *tp)
3864{
3865 rtl_writephy(tp, 0x1f, 0x0000);
3866 rtl_writephy(tp, MII_BMCR, BMCR_PDOWN);
3867}
3868
3869static void r810x_phy_power_up(struct rtl8169_private *tp)
3870{
3871 rtl_writephy(tp, 0x1f, 0x0000);
3872 rtl_writephy(tp, MII_BMCR, BMCR_ANENABLE);
3873}
3874
3875static void r810x_pll_power_down(struct rtl8169_private *tp)
3876{
Hayes Wang00042992012-03-30 14:33:00 +08003877 void __iomem *ioaddr = tp->mmio_addr;
3878
David S. Miller1805b2f2011-10-24 18:18:09 -04003879 if (rtl_wol_pll_power_down(tp))
françois romieu065c27c2011-01-03 15:08:12 +00003880 return;
françois romieu065c27c2011-01-03 15:08:12 +00003881
3882 r810x_phy_power_down(tp);
Hayes Wang00042992012-03-30 14:33:00 +08003883
3884 switch (tp->mac_version) {
3885 case RTL_GIGA_MAC_VER_07:
3886 case RTL_GIGA_MAC_VER_08:
3887 case RTL_GIGA_MAC_VER_09:
3888 case RTL_GIGA_MAC_VER_10:
3889 case RTL_GIGA_MAC_VER_13:
3890 case RTL_GIGA_MAC_VER_16:
3891 break;
3892 default:
3893 RTL_W8(PMCH, RTL_R8(PMCH) & ~0x80);
3894 break;
3895 }
françois romieu065c27c2011-01-03 15:08:12 +00003896}
3897
3898static void r810x_pll_power_up(struct rtl8169_private *tp)
3899{
Hayes Wang00042992012-03-30 14:33:00 +08003900 void __iomem *ioaddr = tp->mmio_addr;
3901
françois romieu065c27c2011-01-03 15:08:12 +00003902 r810x_phy_power_up(tp);
Hayes Wang00042992012-03-30 14:33:00 +08003903
3904 switch (tp->mac_version) {
3905 case RTL_GIGA_MAC_VER_07:
3906 case RTL_GIGA_MAC_VER_08:
3907 case RTL_GIGA_MAC_VER_09:
3908 case RTL_GIGA_MAC_VER_10:
3909 case RTL_GIGA_MAC_VER_13:
3910 case RTL_GIGA_MAC_VER_16:
3911 break;
3912 default:
3913 RTL_W8(PMCH, RTL_R8(PMCH) | 0x80);
3914 break;
3915 }
françois romieu065c27c2011-01-03 15:08:12 +00003916}
3917
3918static void r8168_phy_power_up(struct rtl8169_private *tp)
3919{
3920 rtl_writephy(tp, 0x1f, 0x0000);
hayeswang01dc7fe2011-03-21 01:50:28 +00003921 switch (tp->mac_version) {
3922 case RTL_GIGA_MAC_VER_11:
3923 case RTL_GIGA_MAC_VER_12:
3924 case RTL_GIGA_MAC_VER_17:
3925 case RTL_GIGA_MAC_VER_18:
3926 case RTL_GIGA_MAC_VER_19:
3927 case RTL_GIGA_MAC_VER_20:
3928 case RTL_GIGA_MAC_VER_21:
3929 case RTL_GIGA_MAC_VER_22:
3930 case RTL_GIGA_MAC_VER_23:
3931 case RTL_GIGA_MAC_VER_24:
3932 case RTL_GIGA_MAC_VER_25:
3933 case RTL_GIGA_MAC_VER_26:
3934 case RTL_GIGA_MAC_VER_27:
3935 case RTL_GIGA_MAC_VER_28:
3936 case RTL_GIGA_MAC_VER_31:
3937 rtl_writephy(tp, 0x0e, 0x0000);
3938 break;
3939 default:
3940 break;
3941 }
françois romieu065c27c2011-01-03 15:08:12 +00003942 rtl_writephy(tp, MII_BMCR, BMCR_ANENABLE);
3943}
3944
3945static void r8168_phy_power_down(struct rtl8169_private *tp)
3946{
3947 rtl_writephy(tp, 0x1f, 0x0000);
hayeswang01dc7fe2011-03-21 01:50:28 +00003948 switch (tp->mac_version) {
3949 case RTL_GIGA_MAC_VER_32:
3950 case RTL_GIGA_MAC_VER_33:
3951 rtl_writephy(tp, MII_BMCR, BMCR_ANENABLE | BMCR_PDOWN);
3952 break;
3953
3954 case RTL_GIGA_MAC_VER_11:
3955 case RTL_GIGA_MAC_VER_12:
3956 case RTL_GIGA_MAC_VER_17:
3957 case RTL_GIGA_MAC_VER_18:
3958 case RTL_GIGA_MAC_VER_19:
3959 case RTL_GIGA_MAC_VER_20:
3960 case RTL_GIGA_MAC_VER_21:
3961 case RTL_GIGA_MAC_VER_22:
3962 case RTL_GIGA_MAC_VER_23:
3963 case RTL_GIGA_MAC_VER_24:
3964 case RTL_GIGA_MAC_VER_25:
3965 case RTL_GIGA_MAC_VER_26:
3966 case RTL_GIGA_MAC_VER_27:
3967 case RTL_GIGA_MAC_VER_28:
3968 case RTL_GIGA_MAC_VER_31:
3969 rtl_writephy(tp, 0x0e, 0x0200);
3970 default:
3971 rtl_writephy(tp, MII_BMCR, BMCR_PDOWN);
3972 break;
3973 }
françois romieu065c27c2011-01-03 15:08:12 +00003974}
3975
3976static void r8168_pll_power_down(struct rtl8169_private *tp)
3977{
3978 void __iomem *ioaddr = tp->mmio_addr;
3979
Francois Romieucecb5fd2011-04-01 10:21:07 +02003980 if ((tp->mac_version == RTL_GIGA_MAC_VER_27 ||
3981 tp->mac_version == RTL_GIGA_MAC_VER_28 ||
3982 tp->mac_version == RTL_GIGA_MAC_VER_31) &&
hayeswang4804b3b2011-03-21 01:50:29 +00003983 r8168dp_check_dash(tp)) {
françois romieu065c27c2011-01-03 15:08:12 +00003984 return;
Hayes Wang5d2e1952011-02-22 17:26:22 +08003985 }
françois romieu065c27c2011-01-03 15:08:12 +00003986
Francois Romieucecb5fd2011-04-01 10:21:07 +02003987 if ((tp->mac_version == RTL_GIGA_MAC_VER_23 ||
3988 tp->mac_version == RTL_GIGA_MAC_VER_24) &&
françois romieu065c27c2011-01-03 15:08:12 +00003989 (RTL_R16(CPlusCmd) & ASF)) {
3990 return;
3991 }
3992
hayeswang01dc7fe2011-03-21 01:50:28 +00003993 if (tp->mac_version == RTL_GIGA_MAC_VER_32 ||
3994 tp->mac_version == RTL_GIGA_MAC_VER_33)
Francois Romieufdf6fc02012-07-06 22:40:38 +02003995 rtl_ephy_write(tp, 0x19, 0xff64);
hayeswang01dc7fe2011-03-21 01:50:28 +00003996
David S. Miller1805b2f2011-10-24 18:18:09 -04003997 if (rtl_wol_pll_power_down(tp))
françois romieu065c27c2011-01-03 15:08:12 +00003998 return;
françois romieu065c27c2011-01-03 15:08:12 +00003999
4000 r8168_phy_power_down(tp);
4001
4002 switch (tp->mac_version) {
4003 case RTL_GIGA_MAC_VER_25:
4004 case RTL_GIGA_MAC_VER_26:
Hayes Wang5d2e1952011-02-22 17:26:22 +08004005 case RTL_GIGA_MAC_VER_27:
4006 case RTL_GIGA_MAC_VER_28:
hayeswang4804b3b2011-03-21 01:50:29 +00004007 case RTL_GIGA_MAC_VER_31:
hayeswang01dc7fe2011-03-21 01:50:28 +00004008 case RTL_GIGA_MAC_VER_32:
4009 case RTL_GIGA_MAC_VER_33:
françois romieu065c27c2011-01-03 15:08:12 +00004010 RTL_W8(PMCH, RTL_R8(PMCH) & ~0x80);
4011 break;
4012 }
4013}
4014
4015static void r8168_pll_power_up(struct rtl8169_private *tp)
4016{
4017 void __iomem *ioaddr = tp->mmio_addr;
4018
françois romieu065c27c2011-01-03 15:08:12 +00004019 switch (tp->mac_version) {
4020 case RTL_GIGA_MAC_VER_25:
4021 case RTL_GIGA_MAC_VER_26:
Hayes Wang5d2e1952011-02-22 17:26:22 +08004022 case RTL_GIGA_MAC_VER_27:
4023 case RTL_GIGA_MAC_VER_28:
hayeswang4804b3b2011-03-21 01:50:29 +00004024 case RTL_GIGA_MAC_VER_31:
hayeswang01dc7fe2011-03-21 01:50:28 +00004025 case RTL_GIGA_MAC_VER_32:
4026 case RTL_GIGA_MAC_VER_33:
françois romieu065c27c2011-01-03 15:08:12 +00004027 RTL_W8(PMCH, RTL_R8(PMCH) | 0x80);
4028 break;
4029 }
4030
4031 r8168_phy_power_up(tp);
4032}
4033
Francois Romieud58d46b2011-05-03 16:38:29 +02004034static void rtl_generic_op(struct rtl8169_private *tp,
4035 void (*op)(struct rtl8169_private *))
françois romieu065c27c2011-01-03 15:08:12 +00004036{
4037 if (op)
4038 op(tp);
4039}
4040
4041static void rtl_pll_power_down(struct rtl8169_private *tp)
4042{
Francois Romieud58d46b2011-05-03 16:38:29 +02004043 rtl_generic_op(tp, tp->pll_power_ops.down);
françois romieu065c27c2011-01-03 15:08:12 +00004044}
4045
4046static void rtl_pll_power_up(struct rtl8169_private *tp)
4047{
Francois Romieud58d46b2011-05-03 16:38:29 +02004048 rtl_generic_op(tp, tp->pll_power_ops.up);
françois romieu065c27c2011-01-03 15:08:12 +00004049}
4050
Bill Pembertonbaf63292012-12-03 09:23:28 -05004051static void rtl_init_pll_power_ops(struct rtl8169_private *tp)
françois romieu065c27c2011-01-03 15:08:12 +00004052{
4053 struct pll_power_ops *ops = &tp->pll_power_ops;
4054
4055 switch (tp->mac_version) {
4056 case RTL_GIGA_MAC_VER_07:
4057 case RTL_GIGA_MAC_VER_08:
4058 case RTL_GIGA_MAC_VER_09:
4059 case RTL_GIGA_MAC_VER_10:
4060 case RTL_GIGA_MAC_VER_16:
Hayes Wang5a5e4442011-02-22 17:26:21 +08004061 case RTL_GIGA_MAC_VER_29:
4062 case RTL_GIGA_MAC_VER_30:
Hayes Wang7e18dca2012-03-30 14:33:02 +08004063 case RTL_GIGA_MAC_VER_37:
Hayes Wang5598bfe2012-07-02 17:23:21 +08004064 case RTL_GIGA_MAC_VER_39:
françois romieu065c27c2011-01-03 15:08:12 +00004065 ops->down = r810x_pll_power_down;
4066 ops->up = r810x_pll_power_up;
4067 break;
4068
4069 case RTL_GIGA_MAC_VER_11:
4070 case RTL_GIGA_MAC_VER_12:
4071 case RTL_GIGA_MAC_VER_17:
4072 case RTL_GIGA_MAC_VER_18:
4073 case RTL_GIGA_MAC_VER_19:
4074 case RTL_GIGA_MAC_VER_20:
4075 case RTL_GIGA_MAC_VER_21:
4076 case RTL_GIGA_MAC_VER_22:
4077 case RTL_GIGA_MAC_VER_23:
4078 case RTL_GIGA_MAC_VER_24:
4079 case RTL_GIGA_MAC_VER_25:
4080 case RTL_GIGA_MAC_VER_26:
4081 case RTL_GIGA_MAC_VER_27:
françois romieue6de30d2011-01-03 15:08:37 +00004082 case RTL_GIGA_MAC_VER_28:
hayeswang4804b3b2011-03-21 01:50:29 +00004083 case RTL_GIGA_MAC_VER_31:
hayeswang01dc7fe2011-03-21 01:50:28 +00004084 case RTL_GIGA_MAC_VER_32:
4085 case RTL_GIGA_MAC_VER_33:
Hayes Wang70090422011-07-06 15:58:06 +08004086 case RTL_GIGA_MAC_VER_34:
Hayes Wangc2218922011-09-06 16:55:18 +08004087 case RTL_GIGA_MAC_VER_35:
4088 case RTL_GIGA_MAC_VER_36:
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08004089 case RTL_GIGA_MAC_VER_38:
Hayes Wangc5583862012-07-02 17:23:22 +08004090 case RTL_GIGA_MAC_VER_40:
4091 case RTL_GIGA_MAC_VER_41:
françois romieu065c27c2011-01-03 15:08:12 +00004092 ops->down = r8168_pll_power_down;
4093 ops->up = r8168_pll_power_up;
4094 break;
4095
4096 default:
4097 ops->down = NULL;
4098 ops->up = NULL;
4099 break;
4100 }
4101}
4102
Hayes Wange542a222011-07-06 15:58:04 +08004103static void rtl_init_rxcfg(struct rtl8169_private *tp)
4104{
4105 void __iomem *ioaddr = tp->mmio_addr;
4106
4107 switch (tp->mac_version) {
4108 case RTL_GIGA_MAC_VER_01:
4109 case RTL_GIGA_MAC_VER_02:
4110 case RTL_GIGA_MAC_VER_03:
4111 case RTL_GIGA_MAC_VER_04:
4112 case RTL_GIGA_MAC_VER_05:
4113 case RTL_GIGA_MAC_VER_06:
4114 case RTL_GIGA_MAC_VER_10:
4115 case RTL_GIGA_MAC_VER_11:
4116 case RTL_GIGA_MAC_VER_12:
4117 case RTL_GIGA_MAC_VER_13:
4118 case RTL_GIGA_MAC_VER_14:
4119 case RTL_GIGA_MAC_VER_15:
4120 case RTL_GIGA_MAC_VER_16:
4121 case RTL_GIGA_MAC_VER_17:
4122 RTL_W32(RxConfig, RX_FIFO_THRESH | RX_DMA_BURST);
4123 break;
4124 case RTL_GIGA_MAC_VER_18:
4125 case RTL_GIGA_MAC_VER_19:
4126 case RTL_GIGA_MAC_VER_20:
4127 case RTL_GIGA_MAC_VER_21:
4128 case RTL_GIGA_MAC_VER_22:
4129 case RTL_GIGA_MAC_VER_23:
4130 case RTL_GIGA_MAC_VER_24:
françois romieueb2dc352012-06-20 12:09:18 +00004131 case RTL_GIGA_MAC_VER_34:
Hayes Wange542a222011-07-06 15:58:04 +08004132 RTL_W32(RxConfig, RX128_INT_EN | RX_MULTI_EN | RX_DMA_BURST);
4133 break;
4134 default:
4135 RTL_W32(RxConfig, RX128_INT_EN | RX_DMA_BURST);
4136 break;
4137 }
4138}
4139
Hayes Wang92fc43b2011-07-06 15:58:03 +08004140static void rtl8169_init_ring_indexes(struct rtl8169_private *tp)
4141{
4142 tp->dirty_tx = tp->dirty_rx = tp->cur_tx = tp->cur_rx = 0;
4143}
4144
Francois Romieud58d46b2011-05-03 16:38:29 +02004145static void rtl_hw_jumbo_enable(struct rtl8169_private *tp)
4146{
françois romieu9c5028e2012-03-02 04:43:14 +00004147 void __iomem *ioaddr = tp->mmio_addr;
4148
4149 RTL_W8(Cfg9346, Cfg9346_Unlock);
Francois Romieud58d46b2011-05-03 16:38:29 +02004150 rtl_generic_op(tp, tp->jumbo_ops.enable);
françois romieu9c5028e2012-03-02 04:43:14 +00004151 RTL_W8(Cfg9346, Cfg9346_Lock);
Francois Romieud58d46b2011-05-03 16:38:29 +02004152}
4153
4154static void rtl_hw_jumbo_disable(struct rtl8169_private *tp)
4155{
françois romieu9c5028e2012-03-02 04:43:14 +00004156 void __iomem *ioaddr = tp->mmio_addr;
4157
4158 RTL_W8(Cfg9346, Cfg9346_Unlock);
Francois Romieud58d46b2011-05-03 16:38:29 +02004159 rtl_generic_op(tp, tp->jumbo_ops.disable);
françois romieu9c5028e2012-03-02 04:43:14 +00004160 RTL_W8(Cfg9346, Cfg9346_Lock);
Francois Romieud58d46b2011-05-03 16:38:29 +02004161}
4162
4163static void r8168c_hw_jumbo_enable(struct rtl8169_private *tp)
4164{
4165 void __iomem *ioaddr = tp->mmio_addr;
4166
4167 RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0);
4168 RTL_W8(Config4, RTL_R8(Config4) | Jumbo_En1);
4169 rtl_tx_performance_tweak(tp->pci_dev, 0x2 << MAX_READ_REQUEST_SHIFT);
4170}
4171
4172static void r8168c_hw_jumbo_disable(struct rtl8169_private *tp)
4173{
4174 void __iomem *ioaddr = tp->mmio_addr;
4175
4176 RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0);
4177 RTL_W8(Config4, RTL_R8(Config4) & ~Jumbo_En1);
4178 rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT);
4179}
4180
4181static void r8168dp_hw_jumbo_enable(struct rtl8169_private *tp)
4182{
4183 void __iomem *ioaddr = tp->mmio_addr;
4184
4185 RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0);
4186}
4187
4188static void r8168dp_hw_jumbo_disable(struct rtl8169_private *tp)
4189{
4190 void __iomem *ioaddr = tp->mmio_addr;
4191
4192 RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0);
4193}
4194
4195static void r8168e_hw_jumbo_enable(struct rtl8169_private *tp)
4196{
4197 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieud58d46b2011-05-03 16:38:29 +02004198
4199 RTL_W8(MaxTxPacketSize, 0x3f);
4200 RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0);
4201 RTL_W8(Config4, RTL_R8(Config4) | 0x01);
Francois Romieu4512ff92011-12-22 18:59:37 +01004202 rtl_tx_performance_tweak(tp->pci_dev, 0x2 << MAX_READ_REQUEST_SHIFT);
Francois Romieud58d46b2011-05-03 16:38:29 +02004203}
4204
4205static void r8168e_hw_jumbo_disable(struct rtl8169_private *tp)
4206{
4207 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieud58d46b2011-05-03 16:38:29 +02004208
4209 RTL_W8(MaxTxPacketSize, 0x0c);
4210 RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0);
4211 RTL_W8(Config4, RTL_R8(Config4) & ~0x01);
Francois Romieu4512ff92011-12-22 18:59:37 +01004212 rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT);
Francois Romieud58d46b2011-05-03 16:38:29 +02004213}
4214
4215static void r8168b_0_hw_jumbo_enable(struct rtl8169_private *tp)
4216{
4217 rtl_tx_performance_tweak(tp->pci_dev,
4218 (0x2 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN);
4219}
4220
4221static void r8168b_0_hw_jumbo_disable(struct rtl8169_private *tp)
4222{
4223 rtl_tx_performance_tweak(tp->pci_dev,
4224 (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN);
4225}
4226
4227static void r8168b_1_hw_jumbo_enable(struct rtl8169_private *tp)
4228{
4229 void __iomem *ioaddr = tp->mmio_addr;
4230
4231 r8168b_0_hw_jumbo_enable(tp);
4232
4233 RTL_W8(Config4, RTL_R8(Config4) | (1 << 0));
4234}
4235
4236static void r8168b_1_hw_jumbo_disable(struct rtl8169_private *tp)
4237{
4238 void __iomem *ioaddr = tp->mmio_addr;
4239
4240 r8168b_0_hw_jumbo_disable(tp);
4241
4242 RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0));
4243}
4244
Bill Pembertonbaf63292012-12-03 09:23:28 -05004245static void rtl_init_jumbo_ops(struct rtl8169_private *tp)
Francois Romieud58d46b2011-05-03 16:38:29 +02004246{
4247 struct jumbo_ops *ops = &tp->jumbo_ops;
4248
4249 switch (tp->mac_version) {
4250 case RTL_GIGA_MAC_VER_11:
4251 ops->disable = r8168b_0_hw_jumbo_disable;
4252 ops->enable = r8168b_0_hw_jumbo_enable;
4253 break;
4254 case RTL_GIGA_MAC_VER_12:
4255 case RTL_GIGA_MAC_VER_17:
4256 ops->disable = r8168b_1_hw_jumbo_disable;
4257 ops->enable = r8168b_1_hw_jumbo_enable;
4258 break;
4259 case RTL_GIGA_MAC_VER_18: /* Wild guess. Needs info from Realtek. */
4260 case RTL_GIGA_MAC_VER_19:
4261 case RTL_GIGA_MAC_VER_20:
4262 case RTL_GIGA_MAC_VER_21: /* Wild guess. Needs info from Realtek. */
4263 case RTL_GIGA_MAC_VER_22:
4264 case RTL_GIGA_MAC_VER_23:
4265 case RTL_GIGA_MAC_VER_24:
4266 case RTL_GIGA_MAC_VER_25:
4267 case RTL_GIGA_MAC_VER_26:
4268 ops->disable = r8168c_hw_jumbo_disable;
4269 ops->enable = r8168c_hw_jumbo_enable;
4270 break;
4271 case RTL_GIGA_MAC_VER_27:
4272 case RTL_GIGA_MAC_VER_28:
4273 ops->disable = r8168dp_hw_jumbo_disable;
4274 ops->enable = r8168dp_hw_jumbo_enable;
4275 break;
4276 case RTL_GIGA_MAC_VER_31: /* Wild guess. Needs info from Realtek. */
4277 case RTL_GIGA_MAC_VER_32:
4278 case RTL_GIGA_MAC_VER_33:
4279 case RTL_GIGA_MAC_VER_34:
4280 ops->disable = r8168e_hw_jumbo_disable;
4281 ops->enable = r8168e_hw_jumbo_enable;
4282 break;
4283
4284 /*
4285 * No action needed for jumbo frames with 8169.
4286 * No jumbo for 810x at all.
4287 */
Hayes Wangc5583862012-07-02 17:23:22 +08004288 case RTL_GIGA_MAC_VER_40:
4289 case RTL_GIGA_MAC_VER_41:
Francois Romieud58d46b2011-05-03 16:38:29 +02004290 default:
4291 ops->disable = NULL;
4292 ops->enable = NULL;
4293 break;
4294 }
4295}
4296
Francois Romieuffc46952012-07-06 14:19:23 +02004297DECLARE_RTL_COND(rtl_chipcmd_cond)
4298{
4299 void __iomem *ioaddr = tp->mmio_addr;
4300
4301 return RTL_R8(ChipCmd) & CmdReset;
4302}
4303
Francois Romieu6f43adc2011-04-29 15:05:51 +02004304static void rtl_hw_reset(struct rtl8169_private *tp)
4305{
4306 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu6f43adc2011-04-29 15:05:51 +02004307
Francois Romieu6f43adc2011-04-29 15:05:51 +02004308 RTL_W8(ChipCmd, CmdReset);
4309
Francois Romieuffc46952012-07-06 14:19:23 +02004310 rtl_udelay_loop_wait_low(tp, &rtl_chipcmd_cond, 100, 100);
Francois Romieu6f43adc2011-04-29 15:05:51 +02004311}
4312
Francois Romieub6ffd972011-06-17 17:00:05 +02004313static void rtl_request_uncached_firmware(struct rtl8169_private *tp)
4314{
4315 struct rtl_fw *rtl_fw;
4316 const char *name;
4317 int rc = -ENOMEM;
4318
4319 name = rtl_lookup_firmware_name(tp);
4320 if (!name)
4321 goto out_no_firmware;
4322
4323 rtl_fw = kzalloc(sizeof(*rtl_fw), GFP_KERNEL);
4324 if (!rtl_fw)
4325 goto err_warn;
4326
4327 rc = request_firmware(&rtl_fw->fw, name, &tp->pci_dev->dev);
4328 if (rc < 0)
4329 goto err_free;
4330
Francois Romieufd112f22011-06-18 00:10:29 +02004331 rc = rtl_check_firmware(tp, rtl_fw);
4332 if (rc < 0)
4333 goto err_release_firmware;
4334
Francois Romieub6ffd972011-06-17 17:00:05 +02004335 tp->rtl_fw = rtl_fw;
4336out:
4337 return;
4338
Francois Romieufd112f22011-06-18 00:10:29 +02004339err_release_firmware:
4340 release_firmware(rtl_fw->fw);
Francois Romieub6ffd972011-06-17 17:00:05 +02004341err_free:
4342 kfree(rtl_fw);
4343err_warn:
4344 netif_warn(tp, ifup, tp->dev, "unable to load firmware patch %s (%d)\n",
4345 name, rc);
4346out_no_firmware:
4347 tp->rtl_fw = NULL;
4348 goto out;
4349}
4350
François Romieu953a12c2011-04-24 17:38:48 +02004351static void rtl_request_firmware(struct rtl8169_private *tp)
4352{
Francois Romieub6ffd972011-06-17 17:00:05 +02004353 if (IS_ERR(tp->rtl_fw))
4354 rtl_request_uncached_firmware(tp);
François Romieu953a12c2011-04-24 17:38:48 +02004355}
4356
Hayes Wang92fc43b2011-07-06 15:58:03 +08004357static void rtl_rx_close(struct rtl8169_private *tp)
4358{
4359 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang92fc43b2011-07-06 15:58:03 +08004360
Francois Romieu1687b562011-07-19 17:21:29 +02004361 RTL_W32(RxConfig, RTL_R32(RxConfig) & ~RX_CONFIG_ACCEPT_MASK);
Hayes Wang92fc43b2011-07-06 15:58:03 +08004362}
4363
Francois Romieuffc46952012-07-06 14:19:23 +02004364DECLARE_RTL_COND(rtl_npq_cond)
4365{
4366 void __iomem *ioaddr = tp->mmio_addr;
4367
4368 return RTL_R8(TxPoll) & NPQ;
4369}
4370
4371DECLARE_RTL_COND(rtl_txcfg_empty_cond)
4372{
4373 void __iomem *ioaddr = tp->mmio_addr;
4374
4375 return RTL_R32(TxConfig) & TXCFG_EMPTY;
4376}
4377
françois romieue6de30d2011-01-03 15:08:37 +00004378static void rtl8169_hw_reset(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004379{
françois romieue6de30d2011-01-03 15:08:37 +00004380 void __iomem *ioaddr = tp->mmio_addr;
4381
Linus Torvalds1da177e2005-04-16 15:20:36 -07004382 /* Disable interrupts */
françois romieu811fd302011-12-04 20:30:45 +00004383 rtl8169_irq_mask_and_ack(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004384
Hayes Wang92fc43b2011-07-06 15:58:03 +08004385 rtl_rx_close(tp);
4386
Hayes Wang5d2e1952011-02-22 17:26:22 +08004387 if (tp->mac_version == RTL_GIGA_MAC_VER_27 ||
hayeswang4804b3b2011-03-21 01:50:29 +00004388 tp->mac_version == RTL_GIGA_MAC_VER_28 ||
4389 tp->mac_version == RTL_GIGA_MAC_VER_31) {
Francois Romieuffc46952012-07-06 14:19:23 +02004390 rtl_udelay_loop_wait_low(tp, &rtl_npq_cond, 20, 42*42);
Hayes Wangc2218922011-09-06 16:55:18 +08004391 } else if (tp->mac_version == RTL_GIGA_MAC_VER_34 ||
4392 tp->mac_version == RTL_GIGA_MAC_VER_35 ||
Hayes Wang7e18dca2012-03-30 14:33:02 +08004393 tp->mac_version == RTL_GIGA_MAC_VER_36 ||
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08004394 tp->mac_version == RTL_GIGA_MAC_VER_37 ||
Hayes Wangc5583862012-07-02 17:23:22 +08004395 tp->mac_version == RTL_GIGA_MAC_VER_40 ||
4396 tp->mac_version == RTL_GIGA_MAC_VER_41 ||
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08004397 tp->mac_version == RTL_GIGA_MAC_VER_38) {
David S. Miller8decf862011-09-22 03:23:13 -04004398 RTL_W8(ChipCmd, RTL_R8(ChipCmd) | StopReq);
Francois Romieuffc46952012-07-06 14:19:23 +02004399 rtl_udelay_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 666);
Hayes Wang92fc43b2011-07-06 15:58:03 +08004400 } else {
4401 RTL_W8(ChipCmd, RTL_R8(ChipCmd) | StopReq);
4402 udelay(100);
françois romieue6de30d2011-01-03 15:08:37 +00004403 }
4404
Hayes Wang92fc43b2011-07-06 15:58:03 +08004405 rtl_hw_reset(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004406}
4407
Francois Romieu7f796d832007-06-11 23:04:41 +02004408static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp)
Francois Romieu9cb427b2006-11-02 00:10:16 +01004409{
4410 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu9cb427b2006-11-02 00:10:16 +01004411
4412 /* Set DMA burst size and Interframe Gap Time */
4413 RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) |
4414 (InterFrameGap << TxInterFrameGapShift));
4415}
4416
Francois Romieu07ce4062007-02-23 23:36:39 +01004417static void rtl_hw_start(struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004418{
4419 struct rtl8169_private *tp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004420
Francois Romieu07ce4062007-02-23 23:36:39 +01004421 tp->hw_start(dev);
4422
Francois Romieuda78dbf2012-01-26 14:18:23 +01004423 rtl_irq_enable_all(tp);
Francois Romieu07ce4062007-02-23 23:36:39 +01004424}
4425
Francois Romieu7f796d832007-06-11 23:04:41 +02004426static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp,
4427 void __iomem *ioaddr)
4428{
4429 /*
4430 * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh
4431 * register to be written before TxDescAddrLow to work.
4432 * Switching from MMIO to I/O access fixes the issue as well.
4433 */
4434 RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr) >> 32);
Yang Hongyang284901a2009-04-06 19:01:15 -07004435 RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr) & DMA_BIT_MASK(32));
Francois Romieu7f796d832007-06-11 23:04:41 +02004436 RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32);
Yang Hongyang284901a2009-04-06 19:01:15 -07004437 RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_BIT_MASK(32));
Francois Romieu7f796d832007-06-11 23:04:41 +02004438}
4439
4440static u16 rtl_rw_cpluscmd(void __iomem *ioaddr)
4441{
4442 u16 cmd;
4443
4444 cmd = RTL_R16(CPlusCmd);
4445 RTL_W16(CPlusCmd, cmd);
4446 return cmd;
4447}
4448
Eric Dumazetfdd7b4c2009-06-09 04:01:02 -07004449static void rtl_set_rx_max_size(void __iomem *ioaddr, unsigned int rx_buf_sz)
Francois Romieu7f796d832007-06-11 23:04:41 +02004450{
4451 /* Low hurts. Let's disable the filtering. */
Raimonds Cicans207d6e872009-10-26 10:52:37 +00004452 RTL_W16(RxMaxSize, rx_buf_sz + 1);
Francois Romieu7f796d832007-06-11 23:04:41 +02004453}
4454
Francois Romieu6dccd162007-02-13 23:38:05 +01004455static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version)
4456{
Francois Romieu37441002011-06-17 22:58:54 +02004457 static const struct rtl_cfg2_info {
Francois Romieu6dccd162007-02-13 23:38:05 +01004458 u32 mac_version;
4459 u32 clk;
4460 u32 val;
4461 } cfg2_info [] = {
4462 { RTL_GIGA_MAC_VER_05, PCI_Clock_33MHz, 0x000fff00 }, // 8110SCd
4463 { RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff },
4464 { RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe
4465 { RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff }
Francois Romieu37441002011-06-17 22:58:54 +02004466 };
4467 const struct rtl_cfg2_info *p = cfg2_info;
Francois Romieu6dccd162007-02-13 23:38:05 +01004468 unsigned int i;
4469 u32 clk;
4470
4471 clk = RTL_R8(Config2) & PCI_Clock_66MHz;
Francois Romieucadf1852008-01-03 23:38:38 +01004472 for (i = 0; i < ARRAY_SIZE(cfg2_info); i++, p++) {
Francois Romieu6dccd162007-02-13 23:38:05 +01004473 if ((p->mac_version == mac_version) && (p->clk == clk)) {
4474 RTL_W32(0x7c, p->val);
4475 break;
4476 }
4477 }
4478}
4479
Francois Romieue6b763e2012-03-08 09:35:39 +01004480static void rtl_set_rx_mode(struct net_device *dev)
4481{
4482 struct rtl8169_private *tp = netdev_priv(dev);
4483 void __iomem *ioaddr = tp->mmio_addr;
4484 u32 mc_filter[2]; /* Multicast hash filter */
4485 int rx_mode;
4486 u32 tmp = 0;
4487
4488 if (dev->flags & IFF_PROMISC) {
4489 /* Unconditionally log net taps. */
4490 netif_notice(tp, link, dev, "Promiscuous mode enabled\n");
4491 rx_mode =
4492 AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
4493 AcceptAllPhys;
4494 mc_filter[1] = mc_filter[0] = 0xffffffff;
4495 } else if ((netdev_mc_count(dev) > multicast_filter_limit) ||
4496 (dev->flags & IFF_ALLMULTI)) {
4497 /* Too many to filter perfectly -- accept all multicasts. */
4498 rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
4499 mc_filter[1] = mc_filter[0] = 0xffffffff;
4500 } else {
4501 struct netdev_hw_addr *ha;
4502
4503 rx_mode = AcceptBroadcast | AcceptMyPhys;
4504 mc_filter[1] = mc_filter[0] = 0;
4505 netdev_for_each_mc_addr(ha, dev) {
4506 int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26;
4507 mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
4508 rx_mode |= AcceptMulticast;
4509 }
4510 }
4511
4512 if (dev->features & NETIF_F_RXALL)
4513 rx_mode |= (AcceptErr | AcceptRunt);
4514
4515 tmp = (RTL_R32(RxConfig) & ~RX_CONFIG_ACCEPT_MASK) | rx_mode;
4516
4517 if (tp->mac_version > RTL_GIGA_MAC_VER_06) {
4518 u32 data = mc_filter[0];
4519
4520 mc_filter[0] = swab32(mc_filter[1]);
4521 mc_filter[1] = swab32(data);
4522 }
4523
Nathan Walp04817762012-11-01 12:08:47 +00004524 if (tp->mac_version == RTL_GIGA_MAC_VER_35)
4525 mc_filter[1] = mc_filter[0] = 0xffffffff;
4526
Francois Romieue6b763e2012-03-08 09:35:39 +01004527 RTL_W32(MAR0 + 4, mc_filter[1]);
4528 RTL_W32(MAR0 + 0, mc_filter[0]);
4529
4530 RTL_W32(RxConfig, tmp);
4531}
4532
Francois Romieu07ce4062007-02-23 23:36:39 +01004533static void rtl_hw_start_8169(struct net_device *dev)
4534{
4535 struct rtl8169_private *tp = netdev_priv(dev);
4536 void __iomem *ioaddr = tp->mmio_addr;
4537 struct pci_dev *pdev = tp->pci_dev;
Francois Romieu07ce4062007-02-23 23:36:39 +01004538
Francois Romieu9cb427b2006-11-02 00:10:16 +01004539 if (tp->mac_version == RTL_GIGA_MAC_VER_05) {
4540 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW);
4541 pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08);
4542 }
4543
Linus Torvalds1da177e2005-04-16 15:20:36 -07004544 RTL_W8(Cfg9346, Cfg9346_Unlock);
Francois Romieucecb5fd2011-04-01 10:21:07 +02004545 if (tp->mac_version == RTL_GIGA_MAC_VER_01 ||
4546 tp->mac_version == RTL_GIGA_MAC_VER_02 ||
4547 tp->mac_version == RTL_GIGA_MAC_VER_03 ||
4548 tp->mac_version == RTL_GIGA_MAC_VER_04)
Francois Romieu9cb427b2006-11-02 00:10:16 +01004549 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
4550
Hayes Wange542a222011-07-06 15:58:04 +08004551 rtl_init_rxcfg(tp);
4552
françois romieuf0298f82011-01-03 15:07:42 +00004553 RTL_W8(EarlyTxThres, NoEarlyTx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004554
Eric Dumazet6f0333b2010-10-11 11:17:47 +00004555 rtl_set_rx_max_size(ioaddr, rx_buf_sz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004556
Francois Romieucecb5fd2011-04-01 10:21:07 +02004557 if (tp->mac_version == RTL_GIGA_MAC_VER_01 ||
4558 tp->mac_version == RTL_GIGA_MAC_VER_02 ||
4559 tp->mac_version == RTL_GIGA_MAC_VER_03 ||
4560 tp->mac_version == RTL_GIGA_MAC_VER_04)
Francois Romieuc946b302007-10-04 00:42:50 +02004561 rtl_set_rx_tx_config_registers(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004562
Francois Romieu7f796d832007-06-11 23:04:41 +02004563 tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW;
Francois Romieubcf0bf92006-07-26 23:14:13 +02004564
Francois Romieucecb5fd2011-04-01 10:21:07 +02004565 if (tp->mac_version == RTL_GIGA_MAC_VER_02 ||
4566 tp->mac_version == RTL_GIGA_MAC_VER_03) {
Joe Perches06fa7352007-10-18 21:15:00 +02004567 dprintk("Set MAC Reg C+CR Offset 0xE0. "
Linus Torvalds1da177e2005-04-16 15:20:36 -07004568 "Bit-3 and bit-14 MUST be 1\n");
Francois Romieubcf0bf92006-07-26 23:14:13 +02004569 tp->cp_cmd |= (1 << 14);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004570 }
4571
Francois Romieubcf0bf92006-07-26 23:14:13 +02004572 RTL_W16(CPlusCmd, tp->cp_cmd);
4573
Francois Romieu6dccd162007-02-13 23:38:05 +01004574 rtl8169_set_magic_reg(ioaddr, tp->mac_version);
4575
Linus Torvalds1da177e2005-04-16 15:20:36 -07004576 /*
4577 * Undocumented corner. Supposedly:
4578 * (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets
4579 */
4580 RTL_W16(IntrMitigate, 0x0000);
4581
Francois Romieu7f796d832007-06-11 23:04:41 +02004582 rtl_set_rx_tx_desc_registers(tp, ioaddr);
Francois Romieu9cb427b2006-11-02 00:10:16 +01004583
Francois Romieucecb5fd2011-04-01 10:21:07 +02004584 if (tp->mac_version != RTL_GIGA_MAC_VER_01 &&
4585 tp->mac_version != RTL_GIGA_MAC_VER_02 &&
4586 tp->mac_version != RTL_GIGA_MAC_VER_03 &&
4587 tp->mac_version != RTL_GIGA_MAC_VER_04) {
Francois Romieuc946b302007-10-04 00:42:50 +02004588 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
4589 rtl_set_rx_tx_config_registers(tp);
4590 }
4591
Linus Torvalds1da177e2005-04-16 15:20:36 -07004592 RTL_W8(Cfg9346, Cfg9346_Lock);
Francois Romieub518fa82006-08-16 15:23:13 +02004593
4594 /* Initially a 10 us delay. Turned it into a PCI commit. - FR */
4595 RTL_R8(IntrMask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004596
4597 RTL_W32(RxMissed, 0);
4598
Francois Romieu07ce4062007-02-23 23:36:39 +01004599 rtl_set_rx_mode(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004600
4601 /* no early-rx interrupts */
4602 RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000);
Francois Romieu07ce4062007-02-23 23:36:39 +01004603}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004604
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004605static void rtl_csi_write(struct rtl8169_private *tp, int addr, int value)
4606{
4607 if (tp->csi_ops.write)
Francois Romieu52989f02012-07-06 13:37:00 +02004608 tp->csi_ops.write(tp, addr, value);
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004609}
4610
4611static u32 rtl_csi_read(struct rtl8169_private *tp, int addr)
4612{
Francois Romieu52989f02012-07-06 13:37:00 +02004613 return tp->csi_ops.read ? tp->csi_ops.read(tp, addr) : ~0;
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004614}
4615
4616static void rtl_csi_access_enable(struct rtl8169_private *tp, u32 bits)
Francois Romieudacf8152008-08-02 20:44:13 +02004617{
4618 u32 csi;
4619
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004620 csi = rtl_csi_read(tp, 0x070c) & 0x00ffffff;
4621 rtl_csi_write(tp, 0x070c, csi | bits);
françois romieu650e8d52011-01-03 15:08:29 +00004622}
4623
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004624static void rtl_csi_access_enable_1(struct rtl8169_private *tp)
françois romieue6de30d2011-01-03 15:08:37 +00004625{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004626 rtl_csi_access_enable(tp, 0x17000000);
françois romieue6de30d2011-01-03 15:08:37 +00004627}
4628
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004629static void rtl_csi_access_enable_2(struct rtl8169_private *tp)
françois romieu650e8d52011-01-03 15:08:29 +00004630{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004631 rtl_csi_access_enable(tp, 0x27000000);
4632}
4633
Francois Romieuffc46952012-07-06 14:19:23 +02004634DECLARE_RTL_COND(rtl_csiar_cond)
4635{
4636 void __iomem *ioaddr = tp->mmio_addr;
4637
4638 return RTL_R32(CSIAR) & CSIAR_FLAG;
4639}
4640
Francois Romieu52989f02012-07-06 13:37:00 +02004641static void r8169_csi_write(struct rtl8169_private *tp, int addr, int value)
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004642{
Francois Romieu52989f02012-07-06 13:37:00 +02004643 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004644
4645 RTL_W32(CSIDR, value);
4646 RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) |
4647 CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT);
4648
Francois Romieuffc46952012-07-06 14:19:23 +02004649 rtl_udelay_loop_wait_low(tp, &rtl_csiar_cond, 10, 100);
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004650}
4651
Francois Romieu52989f02012-07-06 13:37:00 +02004652static u32 r8169_csi_read(struct rtl8169_private *tp, int addr)
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004653{
Francois Romieu52989f02012-07-06 13:37:00 +02004654 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004655
4656 RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) |
4657 CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT);
4658
Francois Romieuffc46952012-07-06 14:19:23 +02004659 return rtl_udelay_loop_wait_high(tp, &rtl_csiar_cond, 10, 100) ?
4660 RTL_R32(CSIDR) : ~0;
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004661}
4662
Francois Romieu52989f02012-07-06 13:37:00 +02004663static void r8402_csi_write(struct rtl8169_private *tp, int addr, int value)
Hayes Wang7e18dca2012-03-30 14:33:02 +08004664{
Francois Romieu52989f02012-07-06 13:37:00 +02004665 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang7e18dca2012-03-30 14:33:02 +08004666
4667 RTL_W32(CSIDR, value);
4668 RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) |
4669 CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT |
4670 CSIAR_FUNC_NIC);
4671
Francois Romieuffc46952012-07-06 14:19:23 +02004672 rtl_udelay_loop_wait_low(tp, &rtl_csiar_cond, 10, 100);
Hayes Wang7e18dca2012-03-30 14:33:02 +08004673}
4674
Francois Romieu52989f02012-07-06 13:37:00 +02004675static u32 r8402_csi_read(struct rtl8169_private *tp, int addr)
Hayes Wang7e18dca2012-03-30 14:33:02 +08004676{
Francois Romieu52989f02012-07-06 13:37:00 +02004677 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang7e18dca2012-03-30 14:33:02 +08004678
4679 RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) | CSIAR_FUNC_NIC |
4680 CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT);
4681
Francois Romieuffc46952012-07-06 14:19:23 +02004682 return rtl_udelay_loop_wait_high(tp, &rtl_csiar_cond, 10, 100) ?
4683 RTL_R32(CSIDR) : ~0;
Hayes Wang7e18dca2012-03-30 14:33:02 +08004684}
4685
Bill Pembertonbaf63292012-12-03 09:23:28 -05004686static void rtl_init_csi_ops(struct rtl8169_private *tp)
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004687{
4688 struct csi_ops *ops = &tp->csi_ops;
4689
4690 switch (tp->mac_version) {
4691 case RTL_GIGA_MAC_VER_01:
4692 case RTL_GIGA_MAC_VER_02:
4693 case RTL_GIGA_MAC_VER_03:
4694 case RTL_GIGA_MAC_VER_04:
4695 case RTL_GIGA_MAC_VER_05:
4696 case RTL_GIGA_MAC_VER_06:
4697 case RTL_GIGA_MAC_VER_10:
4698 case RTL_GIGA_MAC_VER_11:
4699 case RTL_GIGA_MAC_VER_12:
4700 case RTL_GIGA_MAC_VER_13:
4701 case RTL_GIGA_MAC_VER_14:
4702 case RTL_GIGA_MAC_VER_15:
4703 case RTL_GIGA_MAC_VER_16:
4704 case RTL_GIGA_MAC_VER_17:
4705 ops->write = NULL;
4706 ops->read = NULL;
4707 break;
4708
Hayes Wang7e18dca2012-03-30 14:33:02 +08004709 case RTL_GIGA_MAC_VER_37:
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08004710 case RTL_GIGA_MAC_VER_38:
Hayes Wang7e18dca2012-03-30 14:33:02 +08004711 ops->write = r8402_csi_write;
4712 ops->read = r8402_csi_read;
4713 break;
4714
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004715 default:
4716 ops->write = r8169_csi_write;
4717 ops->read = r8169_csi_read;
4718 break;
4719 }
Francois Romieudacf8152008-08-02 20:44:13 +02004720}
4721
4722struct ephy_info {
4723 unsigned int offset;
4724 u16 mask;
4725 u16 bits;
4726};
4727
Francois Romieufdf6fc02012-07-06 22:40:38 +02004728static void rtl_ephy_init(struct rtl8169_private *tp, const struct ephy_info *e,
4729 int len)
Francois Romieudacf8152008-08-02 20:44:13 +02004730{
4731 u16 w;
4732
4733 while (len-- > 0) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02004734 w = (rtl_ephy_read(tp, e->offset) & ~e->mask) | e->bits;
4735 rtl_ephy_write(tp, e->offset, w);
Francois Romieudacf8152008-08-02 20:44:13 +02004736 e++;
4737 }
4738}
4739
Francois Romieub726e492008-06-28 12:22:59 +02004740static void rtl_disable_clock_request(struct pci_dev *pdev)
4741{
Jiang Liu7d7903b2012-07-24 17:20:16 +08004742 pcie_capability_clear_word(pdev, PCI_EXP_LNKCTL,
4743 PCI_EXP_LNKCTL_CLKREQ_EN);
Francois Romieub726e492008-06-28 12:22:59 +02004744}
4745
françois romieue6de30d2011-01-03 15:08:37 +00004746static void rtl_enable_clock_request(struct pci_dev *pdev)
4747{
Jiang Liu7d7903b2012-07-24 17:20:16 +08004748 pcie_capability_set_word(pdev, PCI_EXP_LNKCTL,
4749 PCI_EXP_LNKCTL_CLKREQ_EN);
françois romieue6de30d2011-01-03 15:08:37 +00004750}
4751
Francois Romieub726e492008-06-28 12:22:59 +02004752#define R8168_CPCMD_QUIRK_MASK (\
4753 EnableBist | \
4754 Mac_dbgo_oe | \
4755 Force_half_dup | \
4756 Force_rxflow_en | \
4757 Force_txflow_en | \
4758 Cxpl_dbg_sel | \
4759 ASF | \
4760 PktCntrDisable | \
4761 Mac_dbgo_sel)
4762
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004763static void rtl_hw_start_8168bb(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004764{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004765 void __iomem *ioaddr = tp->mmio_addr;
4766 struct pci_dev *pdev = tp->pci_dev;
4767
Francois Romieub726e492008-06-28 12:22:59 +02004768 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
4769
4770 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
4771
Francois Romieu2e68ae42008-06-28 12:00:55 +02004772 rtl_tx_performance_tweak(pdev,
4773 (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN);
Francois Romieu219a1e92008-06-28 11:58:39 +02004774}
4775
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004776static void rtl_hw_start_8168bef(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004777{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004778 void __iomem *ioaddr = tp->mmio_addr;
4779
4780 rtl_hw_start_8168bb(tp);
Francois Romieub726e492008-06-28 12:22:59 +02004781
françois romieuf0298f82011-01-03 15:07:42 +00004782 RTL_W8(MaxTxPacketSize, TxPacketMax);
Francois Romieub726e492008-06-28 12:22:59 +02004783
4784 RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0));
Francois Romieu219a1e92008-06-28 11:58:39 +02004785}
4786
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004787static void __rtl_hw_start_8168cp(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004788{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004789 void __iomem *ioaddr = tp->mmio_addr;
4790 struct pci_dev *pdev = tp->pci_dev;
4791
Francois Romieub726e492008-06-28 12:22:59 +02004792 RTL_W8(Config1, RTL_R8(Config1) | Speed_down);
4793
4794 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
4795
Francois Romieu219a1e92008-06-28 11:58:39 +02004796 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
Francois Romieub726e492008-06-28 12:22:59 +02004797
4798 rtl_disable_clock_request(pdev);
4799
4800 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
Francois Romieu219a1e92008-06-28 11:58:39 +02004801}
4802
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004803static void rtl_hw_start_8168cp_1(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004804{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08004805 static const struct ephy_info e_info_8168cp[] = {
Francois Romieub726e492008-06-28 12:22:59 +02004806 { 0x01, 0, 0x0001 },
4807 { 0x02, 0x0800, 0x1000 },
4808 { 0x03, 0, 0x0042 },
4809 { 0x06, 0x0080, 0x0000 },
4810 { 0x07, 0, 0x2000 }
4811 };
4812
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004813 rtl_csi_access_enable_2(tp);
Francois Romieub726e492008-06-28 12:22:59 +02004814
Francois Romieufdf6fc02012-07-06 22:40:38 +02004815 rtl_ephy_init(tp, e_info_8168cp, ARRAY_SIZE(e_info_8168cp));
Francois Romieub726e492008-06-28 12:22:59 +02004816
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004817 __rtl_hw_start_8168cp(tp);
Francois Romieu219a1e92008-06-28 11:58:39 +02004818}
4819
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004820static void rtl_hw_start_8168cp_2(struct rtl8169_private *tp)
Francois Romieuef3386f2008-06-29 12:24:30 +02004821{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004822 void __iomem *ioaddr = tp->mmio_addr;
4823 struct pci_dev *pdev = tp->pci_dev;
4824
4825 rtl_csi_access_enable_2(tp);
Francois Romieuef3386f2008-06-29 12:24:30 +02004826
4827 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
4828
4829 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
4830
4831 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
4832}
4833
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004834static void rtl_hw_start_8168cp_3(struct rtl8169_private *tp)
Francois Romieu7f3e3d32008-07-20 18:53:20 +02004835{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004836 void __iomem *ioaddr = tp->mmio_addr;
4837 struct pci_dev *pdev = tp->pci_dev;
4838
4839 rtl_csi_access_enable_2(tp);
Francois Romieu7f3e3d32008-07-20 18:53:20 +02004840
4841 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
4842
4843 /* Magic. */
4844 RTL_W8(DBG_REG, 0x20);
4845
françois romieuf0298f82011-01-03 15:07:42 +00004846 RTL_W8(MaxTxPacketSize, TxPacketMax);
Francois Romieu7f3e3d32008-07-20 18:53:20 +02004847
4848 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
4849
4850 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
4851}
4852
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004853static void rtl_hw_start_8168c_1(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004854{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004855 void __iomem *ioaddr = tp->mmio_addr;
Alexey Dobriyan350f7592009-11-25 15:54:21 -08004856 static const struct ephy_info e_info_8168c_1[] = {
Francois Romieub726e492008-06-28 12:22:59 +02004857 { 0x02, 0x0800, 0x1000 },
4858 { 0x03, 0, 0x0002 },
4859 { 0x06, 0x0080, 0x0000 }
4860 };
4861
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004862 rtl_csi_access_enable_2(tp);
Francois Romieub726e492008-06-28 12:22:59 +02004863
4864 RTL_W8(DBG_REG, 0x06 | FIX_NAK_1 | FIX_NAK_2);
4865
Francois Romieufdf6fc02012-07-06 22:40:38 +02004866 rtl_ephy_init(tp, e_info_8168c_1, ARRAY_SIZE(e_info_8168c_1));
Francois Romieub726e492008-06-28 12:22:59 +02004867
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004868 __rtl_hw_start_8168cp(tp);
Francois Romieu219a1e92008-06-28 11:58:39 +02004869}
4870
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004871static void rtl_hw_start_8168c_2(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004872{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08004873 static const struct ephy_info e_info_8168c_2[] = {
Francois Romieub726e492008-06-28 12:22:59 +02004874 { 0x01, 0, 0x0001 },
4875 { 0x03, 0x0400, 0x0220 }
4876 };
4877
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004878 rtl_csi_access_enable_2(tp);
Francois Romieub726e492008-06-28 12:22:59 +02004879
Francois Romieufdf6fc02012-07-06 22:40:38 +02004880 rtl_ephy_init(tp, e_info_8168c_2, ARRAY_SIZE(e_info_8168c_2));
Francois Romieub726e492008-06-28 12:22:59 +02004881
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004882 __rtl_hw_start_8168cp(tp);
Francois Romieu219a1e92008-06-28 11:58:39 +02004883}
4884
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004885static void rtl_hw_start_8168c_3(struct rtl8169_private *tp)
Francois Romieu197ff762008-06-28 13:16:02 +02004886{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004887 rtl_hw_start_8168c_2(tp);
Francois Romieu197ff762008-06-28 13:16:02 +02004888}
4889
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004890static void rtl_hw_start_8168c_4(struct rtl8169_private *tp)
Francois Romieu6fb07052008-06-29 11:54:28 +02004891{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004892 rtl_csi_access_enable_2(tp);
Francois Romieu6fb07052008-06-29 11:54:28 +02004893
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004894 __rtl_hw_start_8168cp(tp);
Francois Romieu6fb07052008-06-29 11:54:28 +02004895}
4896
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004897static void rtl_hw_start_8168d(struct rtl8169_private *tp)
Francois Romieu5b538df2008-07-20 16:22:45 +02004898{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004899 void __iomem *ioaddr = tp->mmio_addr;
4900 struct pci_dev *pdev = tp->pci_dev;
4901
4902 rtl_csi_access_enable_2(tp);
Francois Romieu5b538df2008-07-20 16:22:45 +02004903
4904 rtl_disable_clock_request(pdev);
4905
françois romieuf0298f82011-01-03 15:07:42 +00004906 RTL_W8(MaxTxPacketSize, TxPacketMax);
Francois Romieu5b538df2008-07-20 16:22:45 +02004907
4908 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
4909
4910 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
4911}
4912
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004913static void rtl_hw_start_8168dp(struct rtl8169_private *tp)
hayeswang4804b3b2011-03-21 01:50:29 +00004914{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004915 void __iomem *ioaddr = tp->mmio_addr;
4916 struct pci_dev *pdev = tp->pci_dev;
4917
4918 rtl_csi_access_enable_1(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00004919
4920 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
4921
4922 RTL_W8(MaxTxPacketSize, TxPacketMax);
4923
4924 rtl_disable_clock_request(pdev);
4925}
4926
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004927static void rtl_hw_start_8168d_4(struct rtl8169_private *tp)
françois romieue6de30d2011-01-03 15:08:37 +00004928{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004929 void __iomem *ioaddr = tp->mmio_addr;
4930 struct pci_dev *pdev = tp->pci_dev;
françois romieue6de30d2011-01-03 15:08:37 +00004931 static const struct ephy_info e_info_8168d_4[] = {
4932 { 0x0b, ~0, 0x48 },
4933 { 0x19, 0x20, 0x50 },
4934 { 0x0c, ~0, 0x20 }
4935 };
4936 int i;
4937
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004938 rtl_csi_access_enable_1(tp);
françois romieue6de30d2011-01-03 15:08:37 +00004939
4940 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
4941
4942 RTL_W8(MaxTxPacketSize, TxPacketMax);
4943
4944 for (i = 0; i < ARRAY_SIZE(e_info_8168d_4); i++) {
4945 const struct ephy_info *e = e_info_8168d_4 + i;
4946 u16 w;
4947
Francois Romieufdf6fc02012-07-06 22:40:38 +02004948 w = rtl_ephy_read(tp, e->offset);
4949 rtl_ephy_write(tp, 0x03, (w & e->mask) | e->bits);
françois romieue6de30d2011-01-03 15:08:37 +00004950 }
4951
4952 rtl_enable_clock_request(pdev);
4953}
4954
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004955static void rtl_hw_start_8168e_1(struct rtl8169_private *tp)
hayeswang01dc7fe2011-03-21 01:50:28 +00004956{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004957 void __iomem *ioaddr = tp->mmio_addr;
4958 struct pci_dev *pdev = tp->pci_dev;
Hayes Wang70090422011-07-06 15:58:06 +08004959 static const struct ephy_info e_info_8168e_1[] = {
hayeswang01dc7fe2011-03-21 01:50:28 +00004960 { 0x00, 0x0200, 0x0100 },
4961 { 0x00, 0x0000, 0x0004 },
4962 { 0x06, 0x0002, 0x0001 },
4963 { 0x06, 0x0000, 0x0030 },
4964 { 0x07, 0x0000, 0x2000 },
4965 { 0x00, 0x0000, 0x0020 },
4966 { 0x03, 0x5800, 0x2000 },
4967 { 0x03, 0x0000, 0x0001 },
4968 { 0x01, 0x0800, 0x1000 },
4969 { 0x07, 0x0000, 0x4000 },
4970 { 0x1e, 0x0000, 0x2000 },
4971 { 0x19, 0xffff, 0xfe6c },
4972 { 0x0a, 0x0000, 0x0040 }
4973 };
4974
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004975 rtl_csi_access_enable_2(tp);
hayeswang01dc7fe2011-03-21 01:50:28 +00004976
Francois Romieufdf6fc02012-07-06 22:40:38 +02004977 rtl_ephy_init(tp, e_info_8168e_1, ARRAY_SIZE(e_info_8168e_1));
hayeswang01dc7fe2011-03-21 01:50:28 +00004978
4979 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
4980
4981 RTL_W8(MaxTxPacketSize, TxPacketMax);
4982
4983 rtl_disable_clock_request(pdev);
4984
4985 /* Reset tx FIFO pointer */
Francois Romieucecb5fd2011-04-01 10:21:07 +02004986 RTL_W32(MISC, RTL_R32(MISC) | TXPLA_RST);
4987 RTL_W32(MISC, RTL_R32(MISC) & ~TXPLA_RST);
hayeswang01dc7fe2011-03-21 01:50:28 +00004988
Francois Romieucecb5fd2011-04-01 10:21:07 +02004989 RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en);
hayeswang01dc7fe2011-03-21 01:50:28 +00004990}
4991
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004992static void rtl_hw_start_8168e_2(struct rtl8169_private *tp)
Hayes Wang70090422011-07-06 15:58:06 +08004993{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004994 void __iomem *ioaddr = tp->mmio_addr;
4995 struct pci_dev *pdev = tp->pci_dev;
Hayes Wang70090422011-07-06 15:58:06 +08004996 static const struct ephy_info e_info_8168e_2[] = {
4997 { 0x09, 0x0000, 0x0080 },
4998 { 0x19, 0x0000, 0x0224 }
4999 };
5000
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005001 rtl_csi_access_enable_1(tp);
Hayes Wang70090422011-07-06 15:58:06 +08005002
Francois Romieufdf6fc02012-07-06 22:40:38 +02005003 rtl_ephy_init(tp, e_info_8168e_2, ARRAY_SIZE(e_info_8168e_2));
Hayes Wang70090422011-07-06 15:58:06 +08005004
5005 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5006
Francois Romieufdf6fc02012-07-06 22:40:38 +02005007 rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5008 rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5009 rtl_eri_write(tp, 0xc8, ERIAR_MASK_1111, 0x00100002, ERIAR_EXGMAC);
5010 rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC);
5011 rtl_eri_write(tp, 0xcc, ERIAR_MASK_1111, 0x00000050, ERIAR_EXGMAC);
5012 rtl_eri_write(tp, 0xd0, ERIAR_MASK_1111, 0x07ff0060, ERIAR_EXGMAC);
5013 rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC);
5014 rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0xff00, ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08005015
Hayes Wang3090bd92011-09-06 16:55:15 +08005016 RTL_W8(MaxTxPacketSize, EarlySize);
Hayes Wang70090422011-07-06 15:58:06 +08005017
Hayes Wang70090422011-07-06 15:58:06 +08005018 RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
5019 RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
5020
5021 /* Adjust EEE LED frequency */
5022 RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07);
5023
5024 RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
5025 RTL_W32(MISC, RTL_R32(MISC) | PWM_EN);
hayeswangd64ec842012-11-01 16:46:28 +00005026 RTL_W8(Config5, (RTL_R8(Config5) & ~Spi_en) | ASPM_en);
5027 RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
Hayes Wang70090422011-07-06 15:58:06 +08005028}
5029
Hayes Wang5f886e02012-03-30 14:33:03 +08005030static void rtl_hw_start_8168f(struct rtl8169_private *tp)
Hayes Wangc2218922011-09-06 16:55:18 +08005031{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005032 void __iomem *ioaddr = tp->mmio_addr;
5033 struct pci_dev *pdev = tp->pci_dev;
Hayes Wangc2218922011-09-06 16:55:18 +08005034
Hayes Wang5f886e02012-03-30 14:33:03 +08005035 rtl_csi_access_enable_2(tp);
Hayes Wangc2218922011-09-06 16:55:18 +08005036
5037 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5038
Francois Romieufdf6fc02012-07-06 22:40:38 +02005039 rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5040 rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5041 rtl_eri_write(tp, 0xc8, ERIAR_MASK_1111, 0x00100002, ERIAR_EXGMAC);
5042 rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC);
5043 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC);
5044 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC);
5045 rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC);
5046 rtl_w1w0_eri(tp, 0x1d0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC);
5047 rtl_eri_write(tp, 0xcc, ERIAR_MASK_1111, 0x00000050, ERIAR_EXGMAC);
5048 rtl_eri_write(tp, 0xd0, ERIAR_MASK_1111, 0x00000060, ERIAR_EXGMAC);
Hayes Wangc2218922011-09-06 16:55:18 +08005049
5050 RTL_W8(MaxTxPacketSize, EarlySize);
5051
Hayes Wangc2218922011-09-06 16:55:18 +08005052 RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
5053 RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
Hayes Wangc2218922011-09-06 16:55:18 +08005054 RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
hayeswangd64ec842012-11-01 16:46:28 +00005055 RTL_W32(MISC, RTL_R32(MISC) | PWM_EN | FORCE_CLK);
5056 RTL_W8(Config5, (RTL_R8(Config5) & ~Spi_en) | ASPM_en);
5057 RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
Hayes Wangc2218922011-09-06 16:55:18 +08005058}
5059
Hayes Wang5f886e02012-03-30 14:33:03 +08005060static void rtl_hw_start_8168f_1(struct rtl8169_private *tp)
5061{
5062 void __iomem *ioaddr = tp->mmio_addr;
5063 static const struct ephy_info e_info_8168f_1[] = {
5064 { 0x06, 0x00c0, 0x0020 },
5065 { 0x08, 0x0001, 0x0002 },
5066 { 0x09, 0x0000, 0x0080 },
5067 { 0x19, 0x0000, 0x0224 }
5068 };
5069
5070 rtl_hw_start_8168f(tp);
5071
Francois Romieufdf6fc02012-07-06 22:40:38 +02005072 rtl_ephy_init(tp, e_info_8168f_1, ARRAY_SIZE(e_info_8168f_1));
Hayes Wang5f886e02012-03-30 14:33:03 +08005073
Francois Romieufdf6fc02012-07-06 22:40:38 +02005074 rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0xff00, ERIAR_EXGMAC);
Hayes Wang5f886e02012-03-30 14:33:03 +08005075
5076 /* Adjust EEE LED frequency */
5077 RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07);
5078}
5079
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005080static void rtl_hw_start_8411(struct rtl8169_private *tp)
5081{
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005082 static const struct ephy_info e_info_8168f_1[] = {
5083 { 0x06, 0x00c0, 0x0020 },
5084 { 0x0f, 0xffff, 0x5200 },
5085 { 0x1e, 0x0000, 0x4000 },
5086 { 0x19, 0x0000, 0x0224 }
5087 };
5088
5089 rtl_hw_start_8168f(tp);
5090
Francois Romieufdf6fc02012-07-06 22:40:38 +02005091 rtl_ephy_init(tp, e_info_8168f_1, ARRAY_SIZE(e_info_8168f_1));
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005092
Francois Romieufdf6fc02012-07-06 22:40:38 +02005093 rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0x0000, ERIAR_EXGMAC);
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005094}
5095
Hayes Wangc5583862012-07-02 17:23:22 +08005096static void rtl_hw_start_8168g_1(struct rtl8169_private *tp)
5097{
5098 void __iomem *ioaddr = tp->mmio_addr;
5099 struct pci_dev *pdev = tp->pci_dev;
5100
5101 rtl_eri_write(tp, 0xc8, ERIAR_MASK_0101, 0x080002, ERIAR_EXGMAC);
5102 rtl_eri_write(tp, 0xcc, ERIAR_MASK_0001, 0x38, ERIAR_EXGMAC);
5103 rtl_eri_write(tp, 0xd0, ERIAR_MASK_0001, 0x48, ERIAR_EXGMAC);
5104 rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC);
5105
5106 rtl_csi_access_enable_1(tp);
5107
5108 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5109
5110 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC);
5111 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC);
5112
5113 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
hayeswangd64ec842012-11-01 16:46:28 +00005114 RTL_W32(MISC, (RTL_R32(MISC) | FORCE_CLK) & ~RXDV_GATED_EN);
Hayes Wangc5583862012-07-02 17:23:22 +08005115 RTL_W8(MaxTxPacketSize, EarlySize);
hayeswangd64ec842012-11-01 16:46:28 +00005116 RTL_W8(Config5, RTL_R8(Config5) | ASPM_en);
5117 RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
Hayes Wangc5583862012-07-02 17:23:22 +08005118
5119 rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5120 rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5121
5122 /* Adjust EEE LED frequency */
5123 RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07);
5124
5125 rtl_w1w0_eri(tp, 0x2fc, ERIAR_MASK_0001, 0x01, 0x02, ERIAR_EXGMAC);
5126}
5127
Francois Romieu07ce4062007-02-23 23:36:39 +01005128static void rtl_hw_start_8168(struct net_device *dev)
5129{
Francois Romieu2dd99532007-06-11 23:22:52 +02005130 struct rtl8169_private *tp = netdev_priv(dev);
5131 void __iomem *ioaddr = tp->mmio_addr;
5132
5133 RTL_W8(Cfg9346, Cfg9346_Unlock);
5134
françois romieuf0298f82011-01-03 15:07:42 +00005135 RTL_W8(MaxTxPacketSize, TxPacketMax);
Francois Romieu2dd99532007-06-11 23:22:52 +02005136
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005137 rtl_set_rx_max_size(ioaddr, rx_buf_sz);
Francois Romieu2dd99532007-06-11 23:22:52 +02005138
Francois Romieu0e485152007-02-20 00:00:26 +01005139 tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1;
Francois Romieu2dd99532007-06-11 23:22:52 +02005140
5141 RTL_W16(CPlusCmd, tp->cp_cmd);
5142
Francois Romieu0e485152007-02-20 00:00:26 +01005143 RTL_W16(IntrMitigate, 0x5151);
5144
5145 /* Work around for RxFIFO overflow. */
françois romieu811fd302011-12-04 20:30:45 +00005146 if (tp->mac_version == RTL_GIGA_MAC_VER_11) {
Francois Romieuda78dbf2012-01-26 14:18:23 +01005147 tp->event_slow |= RxFIFOOver | PCSTimeout;
5148 tp->event_slow &= ~RxOverflow;
Francois Romieu0e485152007-02-20 00:00:26 +01005149 }
Francois Romieu2dd99532007-06-11 23:22:52 +02005150
5151 rtl_set_rx_tx_desc_registers(tp, ioaddr);
5152
Francois Romieub8363902008-06-01 12:31:57 +02005153 rtl_set_rx_mode(dev);
5154
5155 RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) |
5156 (InterFrameGap << TxInterFrameGapShift));
Francois Romieu2dd99532007-06-11 23:22:52 +02005157
5158 RTL_R8(IntrMask);
5159
Francois Romieu219a1e92008-06-28 11:58:39 +02005160 switch (tp->mac_version) {
5161 case RTL_GIGA_MAC_VER_11:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005162 rtl_hw_start_8168bb(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005163 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005164
5165 case RTL_GIGA_MAC_VER_12:
5166 case RTL_GIGA_MAC_VER_17:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005167 rtl_hw_start_8168bef(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005168 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005169
5170 case RTL_GIGA_MAC_VER_18:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005171 rtl_hw_start_8168cp_1(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005172 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005173
5174 case RTL_GIGA_MAC_VER_19:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005175 rtl_hw_start_8168c_1(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005176 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005177
5178 case RTL_GIGA_MAC_VER_20:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005179 rtl_hw_start_8168c_2(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005180 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005181
Francois Romieu197ff762008-06-28 13:16:02 +02005182 case RTL_GIGA_MAC_VER_21:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005183 rtl_hw_start_8168c_3(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005184 break;
Francois Romieu197ff762008-06-28 13:16:02 +02005185
Francois Romieu6fb07052008-06-29 11:54:28 +02005186 case RTL_GIGA_MAC_VER_22:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005187 rtl_hw_start_8168c_4(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005188 break;
Francois Romieu6fb07052008-06-29 11:54:28 +02005189
Francois Romieuef3386f2008-06-29 12:24:30 +02005190 case RTL_GIGA_MAC_VER_23:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005191 rtl_hw_start_8168cp_2(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005192 break;
Francois Romieuef3386f2008-06-29 12:24:30 +02005193
Francois Romieu7f3e3d32008-07-20 18:53:20 +02005194 case RTL_GIGA_MAC_VER_24:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005195 rtl_hw_start_8168cp_3(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005196 break;
Francois Romieu7f3e3d32008-07-20 18:53:20 +02005197
Francois Romieu5b538df2008-07-20 16:22:45 +02005198 case RTL_GIGA_MAC_VER_25:
françois romieudaf9df62009-10-07 12:44:20 +00005199 case RTL_GIGA_MAC_VER_26:
5200 case RTL_GIGA_MAC_VER_27:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005201 rtl_hw_start_8168d(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005202 break;
Francois Romieu5b538df2008-07-20 16:22:45 +02005203
françois romieue6de30d2011-01-03 15:08:37 +00005204 case RTL_GIGA_MAC_VER_28:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005205 rtl_hw_start_8168d_4(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005206 break;
Francois Romieucecb5fd2011-04-01 10:21:07 +02005207
hayeswang4804b3b2011-03-21 01:50:29 +00005208 case RTL_GIGA_MAC_VER_31:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005209 rtl_hw_start_8168dp(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005210 break;
5211
hayeswang01dc7fe2011-03-21 01:50:28 +00005212 case RTL_GIGA_MAC_VER_32:
5213 case RTL_GIGA_MAC_VER_33:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005214 rtl_hw_start_8168e_1(tp);
Hayes Wang70090422011-07-06 15:58:06 +08005215 break;
5216 case RTL_GIGA_MAC_VER_34:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005217 rtl_hw_start_8168e_2(tp);
hayeswang01dc7fe2011-03-21 01:50:28 +00005218 break;
françois romieue6de30d2011-01-03 15:08:37 +00005219
Hayes Wangc2218922011-09-06 16:55:18 +08005220 case RTL_GIGA_MAC_VER_35:
5221 case RTL_GIGA_MAC_VER_36:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005222 rtl_hw_start_8168f_1(tp);
Hayes Wangc2218922011-09-06 16:55:18 +08005223 break;
5224
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005225 case RTL_GIGA_MAC_VER_38:
5226 rtl_hw_start_8411(tp);
5227 break;
5228
Hayes Wangc5583862012-07-02 17:23:22 +08005229 case RTL_GIGA_MAC_VER_40:
5230 case RTL_GIGA_MAC_VER_41:
5231 rtl_hw_start_8168g_1(tp);
5232 break;
5233
Francois Romieu219a1e92008-06-28 11:58:39 +02005234 default:
5235 printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n",
5236 dev->name, tp->mac_version);
hayeswang4804b3b2011-03-21 01:50:29 +00005237 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005238 }
Francois Romieu2dd99532007-06-11 23:22:52 +02005239
Francois Romieu0e485152007-02-20 00:00:26 +01005240 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
5241
Francois Romieub8363902008-06-01 12:31:57 +02005242 RTL_W8(Cfg9346, Cfg9346_Lock);
5243
Francois Romieu2dd99532007-06-11 23:22:52 +02005244 RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000);
Francois Romieu07ce4062007-02-23 23:36:39 +01005245}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005246
Francois Romieu2857ffb2008-08-02 21:08:49 +02005247#define R810X_CPCMD_QUIRK_MASK (\
5248 EnableBist | \
5249 Mac_dbgo_oe | \
5250 Force_half_dup | \
françois romieu5edcc532009-08-10 19:41:52 +00005251 Force_rxflow_en | \
Francois Romieu2857ffb2008-08-02 21:08:49 +02005252 Force_txflow_en | \
5253 Cxpl_dbg_sel | \
5254 ASF | \
5255 PktCntrDisable | \
Hayes Wangd24e9aa2011-02-22 17:26:19 +08005256 Mac_dbgo_sel)
Francois Romieu2857ffb2008-08-02 21:08:49 +02005257
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005258static void rtl_hw_start_8102e_1(struct rtl8169_private *tp)
Francois Romieu2857ffb2008-08-02 21:08:49 +02005259{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005260 void __iomem *ioaddr = tp->mmio_addr;
5261 struct pci_dev *pdev = tp->pci_dev;
Alexey Dobriyan350f7592009-11-25 15:54:21 -08005262 static const struct ephy_info e_info_8102e_1[] = {
Francois Romieu2857ffb2008-08-02 21:08:49 +02005263 { 0x01, 0, 0x6e65 },
5264 { 0x02, 0, 0x091f },
5265 { 0x03, 0, 0xc2f9 },
5266 { 0x06, 0, 0xafb5 },
5267 { 0x07, 0, 0x0e00 },
5268 { 0x19, 0, 0xec80 },
5269 { 0x01, 0, 0x2e65 },
5270 { 0x01, 0, 0x6e65 }
5271 };
5272 u8 cfg1;
5273
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005274 rtl_csi_access_enable_2(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005275
5276 RTL_W8(DBG_REG, FIX_NAK_1);
5277
5278 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5279
5280 RTL_W8(Config1,
5281 LEDS1 | LEDS0 | Speed_down | MEMMAP | IOMAP | VPD | PMEnable);
5282 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
5283
5284 cfg1 = RTL_R8(Config1);
5285 if ((cfg1 & LEDS0) && (cfg1 & LEDS1))
5286 RTL_W8(Config1, cfg1 & ~LEDS0);
5287
Francois Romieufdf6fc02012-07-06 22:40:38 +02005288 rtl_ephy_init(tp, e_info_8102e_1, ARRAY_SIZE(e_info_8102e_1));
Francois Romieu2857ffb2008-08-02 21:08:49 +02005289}
5290
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005291static void rtl_hw_start_8102e_2(struct rtl8169_private *tp)
Francois Romieu2857ffb2008-08-02 21:08:49 +02005292{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005293 void __iomem *ioaddr = tp->mmio_addr;
5294 struct pci_dev *pdev = tp->pci_dev;
5295
5296 rtl_csi_access_enable_2(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005297
5298 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5299
5300 RTL_W8(Config1, MEMMAP | IOMAP | VPD | PMEnable);
5301 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005302}
5303
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005304static void rtl_hw_start_8102e_3(struct rtl8169_private *tp)
Francois Romieu2857ffb2008-08-02 21:08:49 +02005305{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005306 rtl_hw_start_8102e_2(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005307
Francois Romieufdf6fc02012-07-06 22:40:38 +02005308 rtl_ephy_write(tp, 0x03, 0xc2f9);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005309}
5310
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005311static void rtl_hw_start_8105e_1(struct rtl8169_private *tp)
Hayes Wang5a5e4442011-02-22 17:26:21 +08005312{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005313 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang5a5e4442011-02-22 17:26:21 +08005314 static const struct ephy_info e_info_8105e_1[] = {
5315 { 0x07, 0, 0x4000 },
5316 { 0x19, 0, 0x0200 },
5317 { 0x19, 0, 0x0020 },
5318 { 0x1e, 0, 0x2000 },
5319 { 0x03, 0, 0x0001 },
5320 { 0x19, 0, 0x0100 },
5321 { 0x19, 0, 0x0004 },
5322 { 0x0a, 0, 0x0020 }
5323 };
5324
Francois Romieucecb5fd2011-04-01 10:21:07 +02005325 /* Force LAN exit from ASPM if Rx/Tx are not idle */
Hayes Wang5a5e4442011-02-22 17:26:21 +08005326 RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800);
5327
Francois Romieucecb5fd2011-04-01 10:21:07 +02005328 /* Disable Early Tally Counter */
Hayes Wang5a5e4442011-02-22 17:26:21 +08005329 RTL_W32(FuncEvent, RTL_R32(FuncEvent) & ~0x010000);
5330
5331 RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET);
Hayes Wang4f6b00e52011-07-06 15:58:02 +08005332 RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
hayeswangd64ec842012-11-01 16:46:28 +00005333 RTL_W8(Config5, RTL_R8(Config5) | ASPM_en);
5334 RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
5335 RTL_W32(MISC, RTL_R32(MISC) | FORCE_CLK);
Hayes Wang5a5e4442011-02-22 17:26:21 +08005336
Francois Romieufdf6fc02012-07-06 22:40:38 +02005337 rtl_ephy_init(tp, e_info_8105e_1, ARRAY_SIZE(e_info_8105e_1));
Hayes Wang5a5e4442011-02-22 17:26:21 +08005338}
5339
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005340static void rtl_hw_start_8105e_2(struct rtl8169_private *tp)
Hayes Wang5a5e4442011-02-22 17:26:21 +08005341{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005342 rtl_hw_start_8105e_1(tp);
Francois Romieufdf6fc02012-07-06 22:40:38 +02005343 rtl_ephy_write(tp, 0x1e, rtl_ephy_read(tp, 0x1e) | 0x8000);
Hayes Wang5a5e4442011-02-22 17:26:21 +08005344}
5345
Hayes Wang7e18dca2012-03-30 14:33:02 +08005346static void rtl_hw_start_8402(struct rtl8169_private *tp)
5347{
5348 void __iomem *ioaddr = tp->mmio_addr;
5349 static const struct ephy_info e_info_8402[] = {
5350 { 0x19, 0xffff, 0xff64 },
5351 { 0x1e, 0, 0x4000 }
5352 };
5353
5354 rtl_csi_access_enable_2(tp);
5355
5356 /* Force LAN exit from ASPM if Rx/Tx are not idle */
5357 RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800);
5358
5359 RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
5360 RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
hayeswangd64ec842012-11-01 16:46:28 +00005361 RTL_W8(Config5, RTL_R8(Config5) | ASPM_en);
5362 RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
5363 RTL_W32(MISC, RTL_R32(MISC) | FORCE_CLK);
Hayes Wang7e18dca2012-03-30 14:33:02 +08005364
Francois Romieufdf6fc02012-07-06 22:40:38 +02005365 rtl_ephy_init(tp, e_info_8402, ARRAY_SIZE(e_info_8402));
Hayes Wang7e18dca2012-03-30 14:33:02 +08005366
5367 rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT);
5368
Francois Romieufdf6fc02012-07-06 22:40:38 +02005369 rtl_eri_write(tp, 0xc8, ERIAR_MASK_1111, 0x00000002, ERIAR_EXGMAC);
5370 rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00000006, ERIAR_EXGMAC);
5371 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC);
5372 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC);
5373 rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5374 rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5375 rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0e00, 0xff00, ERIAR_EXGMAC);
Hayes Wang7e18dca2012-03-30 14:33:02 +08005376}
5377
Hayes Wang5598bfe2012-07-02 17:23:21 +08005378static void rtl_hw_start_8106(struct rtl8169_private *tp)
5379{
5380 void __iomem *ioaddr = tp->mmio_addr;
5381
5382 /* Force LAN exit from ASPM if Rx/Tx are not idle */
5383 RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800);
5384
hayeswangd64ec842012-11-01 16:46:28 +00005385 RTL_W32(MISC,
5386 (RTL_R32(MISC) | DISABLE_LAN_EN | FORCE_CLK) & ~EARLY_TALLY_EN);
5387 RTL_W8(Config5, RTL_R8(Config5) | ASPM_en);
5388 RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
Hayes Wang5598bfe2012-07-02 17:23:21 +08005389 RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET);
5390 RTL_W8(DLLPR, RTL_R8(DLLPR) & ~PFM_EN);
5391}
5392
Francois Romieu07ce4062007-02-23 23:36:39 +01005393static void rtl_hw_start_8101(struct net_device *dev)
5394{
Francois Romieucdf1a602007-06-11 23:29:50 +02005395 struct rtl8169_private *tp = netdev_priv(dev);
5396 void __iomem *ioaddr = tp->mmio_addr;
5397 struct pci_dev *pdev = tp->pci_dev;
5398
Francois Romieuda78dbf2012-01-26 14:18:23 +01005399 if (tp->mac_version >= RTL_GIGA_MAC_VER_30)
5400 tp->event_slow &= ~RxFIFOOver;
françois romieu811fd302011-12-04 20:30:45 +00005401
Francois Romieucecb5fd2011-04-01 10:21:07 +02005402 if (tp->mac_version == RTL_GIGA_MAC_VER_13 ||
Jiang Liu7d7903b2012-07-24 17:20:16 +08005403 tp->mac_version == RTL_GIGA_MAC_VER_16)
Bjorn Helgaas8200bc72012-08-22 10:29:42 -06005404 pcie_capability_set_word(pdev, PCI_EXP_DEVCTL,
5405 PCI_EXP_DEVCTL_NOSNOOP_EN);
Francois Romieucdf1a602007-06-11 23:29:50 +02005406
Hayes Wangd24e9aa2011-02-22 17:26:19 +08005407 RTL_W8(Cfg9346, Cfg9346_Unlock);
5408
Francois Romieu2857ffb2008-08-02 21:08:49 +02005409 switch (tp->mac_version) {
5410 case RTL_GIGA_MAC_VER_07:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005411 rtl_hw_start_8102e_1(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005412 break;
5413
5414 case RTL_GIGA_MAC_VER_08:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005415 rtl_hw_start_8102e_3(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005416 break;
5417
5418 case RTL_GIGA_MAC_VER_09:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005419 rtl_hw_start_8102e_2(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005420 break;
Hayes Wang5a5e4442011-02-22 17:26:21 +08005421
5422 case RTL_GIGA_MAC_VER_29:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005423 rtl_hw_start_8105e_1(tp);
Hayes Wang5a5e4442011-02-22 17:26:21 +08005424 break;
5425 case RTL_GIGA_MAC_VER_30:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005426 rtl_hw_start_8105e_2(tp);
Hayes Wang5a5e4442011-02-22 17:26:21 +08005427 break;
Hayes Wang7e18dca2012-03-30 14:33:02 +08005428
5429 case RTL_GIGA_MAC_VER_37:
5430 rtl_hw_start_8402(tp);
5431 break;
Hayes Wang5598bfe2012-07-02 17:23:21 +08005432
5433 case RTL_GIGA_MAC_VER_39:
5434 rtl_hw_start_8106(tp);
5435 break;
Francois Romieucdf1a602007-06-11 23:29:50 +02005436 }
5437
Hayes Wangd24e9aa2011-02-22 17:26:19 +08005438 RTL_W8(Cfg9346, Cfg9346_Lock);
Francois Romieucdf1a602007-06-11 23:29:50 +02005439
françois romieuf0298f82011-01-03 15:07:42 +00005440 RTL_W8(MaxTxPacketSize, TxPacketMax);
Francois Romieucdf1a602007-06-11 23:29:50 +02005441
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005442 rtl_set_rx_max_size(ioaddr, rx_buf_sz);
Francois Romieucdf1a602007-06-11 23:29:50 +02005443
Hayes Wangd24e9aa2011-02-22 17:26:19 +08005444 tp->cp_cmd &= ~R810X_CPCMD_QUIRK_MASK;
Francois Romieucdf1a602007-06-11 23:29:50 +02005445 RTL_W16(CPlusCmd, tp->cp_cmd);
5446
5447 RTL_W16(IntrMitigate, 0x0000);
5448
5449 rtl_set_rx_tx_desc_registers(tp, ioaddr);
5450
5451 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
5452 rtl_set_rx_tx_config_registers(tp);
5453
Francois Romieucdf1a602007-06-11 23:29:50 +02005454 RTL_R8(IntrMask);
5455
Francois Romieucdf1a602007-06-11 23:29:50 +02005456 rtl_set_rx_mode(dev);
5457
5458 RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005459}
5460
5461static int rtl8169_change_mtu(struct net_device *dev, int new_mtu)
5462{
Francois Romieud58d46b2011-05-03 16:38:29 +02005463 struct rtl8169_private *tp = netdev_priv(dev);
5464
5465 if (new_mtu < ETH_ZLEN ||
5466 new_mtu > rtl_chip_infos[tp->mac_version].jumbo_max)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005467 return -EINVAL;
5468
Francois Romieud58d46b2011-05-03 16:38:29 +02005469 if (new_mtu > ETH_DATA_LEN)
5470 rtl_hw_jumbo_enable(tp);
5471 else
5472 rtl_hw_jumbo_disable(tp);
5473
Linus Torvalds1da177e2005-04-16 15:20:36 -07005474 dev->mtu = new_mtu;
Michał Mirosław350fb322011-04-08 06:35:56 +00005475 netdev_update_features(dev);
5476
Stanislaw Gruszka323bb682010-10-20 22:25:41 +00005477 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005478}
5479
5480static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc)
5481{
Al Viro95e09182007-12-22 18:55:39 +00005482 desc->addr = cpu_to_le64(0x0badbadbadbadbadull);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005483 desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask);
5484}
5485
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005486static void rtl8169_free_rx_databuff(struct rtl8169_private *tp,
5487 void **data_buff, struct RxDesc *desc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005488{
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005489 dma_unmap_single(&tp->pci_dev->dev, le64_to_cpu(desc->addr), rx_buf_sz,
Stanislaw Gruszka231aee62010-10-20 22:25:38 +00005490 DMA_FROM_DEVICE);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005491
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005492 kfree(*data_buff);
5493 *data_buff = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005494 rtl8169_make_unusable_by_asic(desc);
5495}
5496
5497static inline void rtl8169_mark_to_asic(struct RxDesc *desc, u32 rx_buf_sz)
5498{
5499 u32 eor = le32_to_cpu(desc->opts1) & RingEnd;
5500
5501 desc->opts1 = cpu_to_le32(DescOwn | eor | rx_buf_sz);
5502}
5503
5504static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping,
5505 u32 rx_buf_sz)
5506{
5507 desc->addr = cpu_to_le64(mapping);
5508 wmb();
5509 rtl8169_mark_to_asic(desc, rx_buf_sz);
5510}
5511
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005512static inline void *rtl8169_align(void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005513{
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005514 return (void *)ALIGN((long)data, 16);
5515}
5516
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005517static struct sk_buff *rtl8169_alloc_rx_data(struct rtl8169_private *tp,
5518 struct RxDesc *desc)
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005519{
5520 void *data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005521 dma_addr_t mapping;
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005522 struct device *d = &tp->pci_dev->dev;
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005523 struct net_device *dev = tp->dev;
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005524 int node = dev->dev.parent ? dev_to_node(dev->dev.parent) : -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005525
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005526 data = kmalloc_node(rx_buf_sz, GFP_KERNEL, node);
5527 if (!data)
5528 return NULL;
Francois Romieue9f63f32007-02-28 23:16:57 +01005529
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005530 if (rtl8169_align(data) != data) {
5531 kfree(data);
5532 data = kmalloc_node(rx_buf_sz + 15, GFP_KERNEL, node);
5533 if (!data)
5534 return NULL;
5535 }
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005536
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005537 mapping = dma_map_single(d, rtl8169_align(data), rx_buf_sz,
Stanislaw Gruszka231aee62010-10-20 22:25:38 +00005538 DMA_FROM_DEVICE);
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005539 if (unlikely(dma_mapping_error(d, mapping))) {
5540 if (net_ratelimit())
5541 netif_err(tp, drv, tp->dev, "Failed to map RX DMA!\n");
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005542 goto err_out;
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005543 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005544
5545 rtl8169_map_to_asic(desc, mapping, rx_buf_sz);
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005546 return data;
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005547
5548err_out:
5549 kfree(data);
5550 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005551}
5552
5553static void rtl8169_rx_clear(struct rtl8169_private *tp)
5554{
Francois Romieu07d3f512007-02-21 22:40:46 +01005555 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005556
5557 for (i = 0; i < NUM_RX_DESC; i++) {
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005558 if (tp->Rx_databuff[i]) {
5559 rtl8169_free_rx_databuff(tp, tp->Rx_databuff + i,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005560 tp->RxDescArray + i);
5561 }
5562 }
5563}
5564
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005565static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005566{
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005567 desc->opts1 |= cpu_to_le32(RingEnd);
5568}
Francois Romieu5b0384f2006-08-16 16:00:01 +02005569
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005570static int rtl8169_rx_fill(struct rtl8169_private *tp)
5571{
5572 unsigned int i;
5573
5574 for (i = 0; i < NUM_RX_DESC; i++) {
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005575 void *data;
Francois Romieu4ae47c22007-06-16 23:28:45 +02005576
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005577 if (tp->Rx_databuff[i])
Linus Torvalds1da177e2005-04-16 15:20:36 -07005578 continue;
Francois Romieubcf0bf92006-07-26 23:14:13 +02005579
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005580 data = rtl8169_alloc_rx_data(tp, tp->RxDescArray + i);
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005581 if (!data) {
5582 rtl8169_make_unusable_by_asic(tp->RxDescArray + i);
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005583 goto err_out;
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005584 }
5585 tp->Rx_databuff[i] = data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005586 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005587
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005588 rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1);
5589 return 0;
5590
5591err_out:
5592 rtl8169_rx_clear(tp);
5593 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005594}
5595
Linus Torvalds1da177e2005-04-16 15:20:36 -07005596static int rtl8169_init_ring(struct net_device *dev)
5597{
5598 struct rtl8169_private *tp = netdev_priv(dev);
5599
5600 rtl8169_init_ring_indexes(tp);
5601
5602 memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info));
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005603 memset(tp->Rx_databuff, 0x0, NUM_RX_DESC * sizeof(void *));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005604
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005605 return rtl8169_rx_fill(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005606}
5607
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005608static void rtl8169_unmap_tx_skb(struct device *d, struct ring_info *tx_skb,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005609 struct TxDesc *desc)
5610{
5611 unsigned int len = tx_skb->len;
5612
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005613 dma_unmap_single(d, le64_to_cpu(desc->addr), len, DMA_TO_DEVICE);
5614
Linus Torvalds1da177e2005-04-16 15:20:36 -07005615 desc->opts1 = 0x00;
5616 desc->opts2 = 0x00;
5617 desc->addr = 0x00;
5618 tx_skb->len = 0;
5619}
5620
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005621static void rtl8169_tx_clear_range(struct rtl8169_private *tp, u32 start,
5622 unsigned int n)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005623{
5624 unsigned int i;
5625
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005626 for (i = 0; i < n; i++) {
5627 unsigned int entry = (start + i) % NUM_TX_DESC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005628 struct ring_info *tx_skb = tp->tx_skb + entry;
5629 unsigned int len = tx_skb->len;
5630
5631 if (len) {
5632 struct sk_buff *skb = tx_skb->skb;
5633
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005634 rtl8169_unmap_tx_skb(&tp->pci_dev->dev, tx_skb,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005635 tp->TxDescArray + entry);
5636 if (skb) {
Stanislaw Gruszkacac4b222010-10-20 22:25:40 +00005637 tp->dev->stats.tx_dropped++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005638 dev_kfree_skb(skb);
5639 tx_skb->skb = NULL;
5640 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005641 }
5642 }
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005643}
5644
5645static void rtl8169_tx_clear(struct rtl8169_private *tp)
5646{
5647 rtl8169_tx_clear_range(tp, tp->dirty_tx, NUM_TX_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005648 tp->cur_tx = tp->dirty_tx = 0;
5649}
5650
Francois Romieu4422bcd2012-01-26 11:23:32 +01005651static void rtl_reset_work(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005652{
David Howellsc4028952006-11-22 14:57:56 +00005653 struct net_device *dev = tp->dev;
Francois Romieu56de4142011-03-15 17:29:31 +01005654 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005655
Francois Romieuda78dbf2012-01-26 14:18:23 +01005656 napi_disable(&tp->napi);
5657 netif_stop_queue(dev);
5658 synchronize_sched();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005659
françois romieuc7c2c392011-12-04 20:30:52 +00005660 rtl8169_hw_reset(tp);
5661
Francois Romieu56de4142011-03-15 17:29:31 +01005662 for (i = 0; i < NUM_RX_DESC; i++)
5663 rtl8169_mark_to_asic(tp->RxDescArray + i, rx_buf_sz);
5664
Linus Torvalds1da177e2005-04-16 15:20:36 -07005665 rtl8169_tx_clear(tp);
françois romieuc7c2c392011-12-04 20:30:52 +00005666 rtl8169_init_ring_indexes(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005667
Francois Romieuda78dbf2012-01-26 14:18:23 +01005668 napi_enable(&tp->napi);
Francois Romieu56de4142011-03-15 17:29:31 +01005669 rtl_hw_start(dev);
5670 netif_wake_queue(dev);
5671 rtl8169_check_link_status(dev, tp, tp->mmio_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005672}
5673
5674static void rtl8169_tx_timeout(struct net_device *dev)
5675{
Francois Romieuda78dbf2012-01-26 14:18:23 +01005676 struct rtl8169_private *tp = netdev_priv(dev);
5677
5678 rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005679}
5680
5681static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb,
Francois Romieu2b7b4312011-04-18 22:53:24 -07005682 u32 *opts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005683{
5684 struct skb_shared_info *info = skb_shinfo(skb);
5685 unsigned int cur_frag, entry;
Jeff Garzika6343af2007-07-17 05:39:58 -04005686 struct TxDesc * uninitialized_var(txd);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005687 struct device *d = &tp->pci_dev->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005688
5689 entry = tp->cur_tx;
5690 for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) {
Eric Dumazet9e903e02011-10-18 21:00:24 +00005691 const skb_frag_t *frag = info->frags + cur_frag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005692 dma_addr_t mapping;
5693 u32 status, len;
5694 void *addr;
5695
5696 entry = (entry + 1) % NUM_TX_DESC;
5697
5698 txd = tp->TxDescArray + entry;
Eric Dumazet9e903e02011-10-18 21:00:24 +00005699 len = skb_frag_size(frag);
Ian Campbell929f6182011-08-31 00:47:06 +00005700 addr = skb_frag_address(frag);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005701 mapping = dma_map_single(d, addr, len, DMA_TO_DEVICE);
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005702 if (unlikely(dma_mapping_error(d, mapping))) {
5703 if (net_ratelimit())
5704 netif_err(tp, drv, tp->dev,
5705 "Failed to map TX fragments DMA!\n");
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005706 goto err_out;
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005707 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005708
Francois Romieucecb5fd2011-04-01 10:21:07 +02005709 /* Anti gcc 2.95.3 bugware (sic) */
Francois Romieu2b7b4312011-04-18 22:53:24 -07005710 status = opts[0] | len |
5711 (RingEnd * !((entry + 1) % NUM_TX_DESC));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005712
5713 txd->opts1 = cpu_to_le32(status);
Francois Romieu2b7b4312011-04-18 22:53:24 -07005714 txd->opts2 = cpu_to_le32(opts[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005715 txd->addr = cpu_to_le64(mapping);
5716
5717 tp->tx_skb[entry].len = len;
5718 }
5719
5720 if (cur_frag) {
5721 tp->tx_skb[entry].skb = skb;
5722 txd->opts1 |= cpu_to_le32(LastFrag);
5723 }
5724
5725 return cur_frag;
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005726
5727err_out:
5728 rtl8169_tx_clear_range(tp, tp->cur_tx + 1, cur_frag);
5729 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005730}
5731
Francois Romieu2b7b4312011-04-18 22:53:24 -07005732static inline void rtl8169_tso_csum(struct rtl8169_private *tp,
5733 struct sk_buff *skb, u32 *opts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005734{
Francois Romieu2b7b4312011-04-18 22:53:24 -07005735 const struct rtl_tx_desc_info *info = tx_desc_info + tp->txd_version;
Michał Mirosław350fb322011-04-08 06:35:56 +00005736 u32 mss = skb_shinfo(skb)->gso_size;
Francois Romieu2b7b4312011-04-18 22:53:24 -07005737 int offset = info->opts_offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005738
Francois Romieu2b7b4312011-04-18 22:53:24 -07005739 if (mss) {
5740 opts[0] |= TD_LSO;
5741 opts[offset] |= min(mss, TD_MSS_MAX) << info->mss_shift;
5742 } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -07005743 const struct iphdr *ip = ip_hdr(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005744
5745 if (ip->protocol == IPPROTO_TCP)
Francois Romieu2b7b4312011-04-18 22:53:24 -07005746 opts[offset] |= info->checksum.tcp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005747 else if (ip->protocol == IPPROTO_UDP)
Francois Romieu2b7b4312011-04-18 22:53:24 -07005748 opts[offset] |= info->checksum.udp;
5749 else
5750 WARN_ON_ONCE(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005751 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005752}
5753
Stephen Hemminger613573252009-08-31 19:50:58 +00005754static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
5755 struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005756{
5757 struct rtl8169_private *tp = netdev_priv(dev);
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005758 unsigned int entry = tp->cur_tx % NUM_TX_DESC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005759 struct TxDesc *txd = tp->TxDescArray + entry;
5760 void __iomem *ioaddr = tp->mmio_addr;
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005761 struct device *d = &tp->pci_dev->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005762 dma_addr_t mapping;
5763 u32 status, len;
Francois Romieu2b7b4312011-04-18 22:53:24 -07005764 u32 opts[2];
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005765 int frags;
Francois Romieu5b0384f2006-08-16 16:00:01 +02005766
Julien Ducourthial477206a2012-05-09 00:00:06 +02005767 if (unlikely(!TX_FRAGS_READY_FOR(tp, skb_shinfo(skb)->nr_frags))) {
Joe Perchesbf82c182010-02-09 11:49:50 +00005768 netif_err(tp, drv, dev, "BUG! Tx Ring full when queue awake!\n");
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005769 goto err_stop_0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005770 }
5771
5772 if (unlikely(le32_to_cpu(txd->opts1) & DescOwn))
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005773 goto err_stop_0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005774
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005775 len = skb_headlen(skb);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005776 mapping = dma_map_single(d, skb->data, len, DMA_TO_DEVICE);
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005777 if (unlikely(dma_mapping_error(d, mapping))) {
5778 if (net_ratelimit())
5779 netif_err(tp, drv, dev, "Failed to map TX DMA!\n");
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005780 goto err_dma_0;
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005781 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005782
5783 tp->tx_skb[entry].len = len;
5784 txd->addr = cpu_to_le64(mapping);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005785
Kirill Smelkov810f4892012-11-10 21:11:02 +04005786 opts[1] = cpu_to_le32(rtl8169_tx_vlan_tag(skb));
Francois Romieu2b7b4312011-04-18 22:53:24 -07005787 opts[0] = DescOwn;
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005788
Francois Romieu2b7b4312011-04-18 22:53:24 -07005789 rtl8169_tso_csum(tp, skb, opts);
5790
5791 frags = rtl8169_xmit_frags(tp, skb, opts);
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005792 if (frags < 0)
5793 goto err_dma_1;
5794 else if (frags)
Francois Romieu2b7b4312011-04-18 22:53:24 -07005795 opts[0] |= FirstFrag;
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005796 else {
Francois Romieu2b7b4312011-04-18 22:53:24 -07005797 opts[0] |= FirstFrag | LastFrag;
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005798 tp->tx_skb[entry].skb = skb;
5799 }
5800
Francois Romieu2b7b4312011-04-18 22:53:24 -07005801 txd->opts2 = cpu_to_le32(opts[1]);
5802
Richard Cochran5047fb52012-03-10 07:29:42 +00005803 skb_tx_timestamp(skb);
5804
Linus Torvalds1da177e2005-04-16 15:20:36 -07005805 wmb();
5806
Francois Romieucecb5fd2011-04-01 10:21:07 +02005807 /* Anti gcc 2.95.3 bugware (sic) */
Francois Romieu2b7b4312011-04-18 22:53:24 -07005808 status = opts[0] | len | (RingEnd * !((entry + 1) % NUM_TX_DESC));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005809 txd->opts1 = cpu_to_le32(status);
5810
Linus Torvalds1da177e2005-04-16 15:20:36 -07005811 tp->cur_tx += frags + 1;
5812
David Dillow4c020a92010-03-03 16:33:10 +00005813 wmb();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005814
Francois Romieucecb5fd2011-04-01 10:21:07 +02005815 RTL_W8(TxPoll, NPQ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005816
Francois Romieuda78dbf2012-01-26 14:18:23 +01005817 mmiowb();
5818
Julien Ducourthial477206a2012-05-09 00:00:06 +02005819 if (!TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS)) {
Francois Romieuae1f23f2012-01-31 00:00:19 +01005820 /* Avoid wrongly optimistic queue wake-up: rtl_tx thread must
5821 * not miss a ring update when it notices a stopped queue.
5822 */
5823 smp_wmb();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005824 netif_stop_queue(dev);
Francois Romieuae1f23f2012-01-31 00:00:19 +01005825 /* Sync with rtl_tx:
5826 * - publish queue status and cur_tx ring index (write barrier)
5827 * - refresh dirty_tx ring index (read barrier).
5828 * May the current thread have a pessimistic view of the ring
5829 * status and forget to wake up queue, a racing rtl_tx thread
5830 * can't.
5831 */
Francois Romieu1e874e02012-01-27 15:05:38 +01005832 smp_mb();
Julien Ducourthial477206a2012-05-09 00:00:06 +02005833 if (TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005834 netif_wake_queue(dev);
5835 }
5836
Stephen Hemminger613573252009-08-31 19:50:58 +00005837 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005838
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005839err_dma_1:
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005840 rtl8169_unmap_tx_skb(d, tp->tx_skb + entry, txd);
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005841err_dma_0:
5842 dev_kfree_skb(skb);
5843 dev->stats.tx_dropped++;
5844 return NETDEV_TX_OK;
5845
5846err_stop_0:
Linus Torvalds1da177e2005-04-16 15:20:36 -07005847 netif_stop_queue(dev);
Francois Romieucebf8cc2007-10-18 12:06:54 +02005848 dev->stats.tx_dropped++;
Stephen Hemminger613573252009-08-31 19:50:58 +00005849 return NETDEV_TX_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005850}
5851
5852static void rtl8169_pcierr_interrupt(struct net_device *dev)
5853{
5854 struct rtl8169_private *tp = netdev_priv(dev);
5855 struct pci_dev *pdev = tp->pci_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005856 u16 pci_status, pci_cmd;
5857
5858 pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd);
5859 pci_read_config_word(pdev, PCI_STATUS, &pci_status);
5860
Joe Perchesbf82c182010-02-09 11:49:50 +00005861 netif_err(tp, intr, dev, "PCI error (cmd = 0x%04x, status = 0x%04x)\n",
5862 pci_cmd, pci_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005863
5864 /*
5865 * The recovery sequence below admits a very elaborated explanation:
5866 * - it seems to work;
Francois Romieud03902b2006-11-23 00:00:42 +01005867 * - I did not see what else could be done;
5868 * - it makes iop3xx happy.
Linus Torvalds1da177e2005-04-16 15:20:36 -07005869 *
5870 * Feel free to adjust to your needs.
5871 */
Francois Romieua27993f2006-12-18 00:04:19 +01005872 if (pdev->broken_parity_status)
Francois Romieud03902b2006-11-23 00:00:42 +01005873 pci_cmd &= ~PCI_COMMAND_PARITY;
5874 else
5875 pci_cmd |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY;
5876
5877 pci_write_config_word(pdev, PCI_COMMAND, pci_cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005878
5879 pci_write_config_word(pdev, PCI_STATUS,
5880 pci_status & (PCI_STATUS_DETECTED_PARITY |
5881 PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_REC_MASTER_ABORT |
5882 PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_SIG_TARGET_ABORT));
5883
5884 /* The infamous DAC f*ckup only happens at boot time */
5885 if ((tp->cp_cmd & PCIDAC) && !tp->dirty_rx && !tp->cur_rx) {
françois romieue6de30d2011-01-03 15:08:37 +00005886 void __iomem *ioaddr = tp->mmio_addr;
5887
Joe Perchesbf82c182010-02-09 11:49:50 +00005888 netif_info(tp, intr, dev, "disabling PCI DAC\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005889 tp->cp_cmd &= ~PCIDAC;
5890 RTL_W16(CPlusCmd, tp->cp_cmd);
5891 dev->features &= ~NETIF_F_HIGHDMA;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005892 }
5893
françois romieue6de30d2011-01-03 15:08:37 +00005894 rtl8169_hw_reset(tp);
Francois Romieud03902b2006-11-23 00:00:42 +01005895
Francois Romieu98ddf982012-01-31 10:47:34 +01005896 rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005897}
5898
Francois Romieuda78dbf2012-01-26 14:18:23 +01005899static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005900{
5901 unsigned int dirty_tx, tx_left;
5902
Linus Torvalds1da177e2005-04-16 15:20:36 -07005903 dirty_tx = tp->dirty_tx;
5904 smp_rmb();
5905 tx_left = tp->cur_tx - dirty_tx;
5906
5907 while (tx_left > 0) {
5908 unsigned int entry = dirty_tx % NUM_TX_DESC;
5909 struct ring_info *tx_skb = tp->tx_skb + entry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005910 u32 status;
5911
5912 rmb();
5913 status = le32_to_cpu(tp->TxDescArray[entry].opts1);
5914 if (status & DescOwn)
5915 break;
5916
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005917 rtl8169_unmap_tx_skb(&tp->pci_dev->dev, tx_skb,
5918 tp->TxDescArray + entry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005919 if (status & LastFrag) {
Francois Romieu17bcb682012-07-23 22:55:55 +02005920 u64_stats_update_begin(&tp->tx_stats.syncp);
5921 tp->tx_stats.packets++;
5922 tp->tx_stats.bytes += tx_skb->skb->len;
5923 u64_stats_update_end(&tp->tx_stats.syncp);
5924 dev_kfree_skb(tx_skb->skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005925 tx_skb->skb = NULL;
5926 }
5927 dirty_tx++;
5928 tx_left--;
5929 }
5930
5931 if (tp->dirty_tx != dirty_tx) {
5932 tp->dirty_tx = dirty_tx;
Francois Romieuae1f23f2012-01-31 00:00:19 +01005933 /* Sync with rtl8169_start_xmit:
5934 * - publish dirty_tx ring index (write barrier)
5935 * - refresh cur_tx ring index and queue status (read barrier)
5936 * May the current thread miss the stopped queue condition,
5937 * a racing xmit thread can only have a right view of the
5938 * ring status.
5939 */
Francois Romieu1e874e02012-01-27 15:05:38 +01005940 smp_mb();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005941 if (netif_queue_stopped(dev) &&
Julien Ducourthial477206a2012-05-09 00:00:06 +02005942 TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005943 netif_wake_queue(dev);
5944 }
Francois Romieud78ae2d2007-08-26 20:08:19 +02005945 /*
5946 * 8168 hack: TxPoll requests are lost when the Tx packets are
5947 * too close. Let's kick an extra TxPoll request when a burst
5948 * of start_xmit activity is detected (if it is not detected,
5949 * it is slow enough). -- FR
5950 */
Francois Romieuda78dbf2012-01-26 14:18:23 +01005951 if (tp->cur_tx != dirty_tx) {
5952 void __iomem *ioaddr = tp->mmio_addr;
5953
Francois Romieud78ae2d2007-08-26 20:08:19 +02005954 RTL_W8(TxPoll, NPQ);
Francois Romieuda78dbf2012-01-26 14:18:23 +01005955 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005956 }
5957}
5958
Francois Romieu126fa4b2005-05-12 20:09:17 -04005959static inline int rtl8169_fragmented_frame(u32 status)
5960{
5961 return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag);
5962}
5963
Eric Dumazetadea1ac72010-09-05 20:04:05 -07005964static inline void rtl8169_rx_csum(struct sk_buff *skb, u32 opts1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005965{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005966 u32 status = opts1 & RxProtoMask;
5967
5968 if (((status == RxProtoTCP) && !(opts1 & TCPFail)) ||
Shan Weid5d3ebe2010-11-12 00:15:25 +00005969 ((status == RxProtoUDP) && !(opts1 & UDPFail)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005970 skb->ip_summed = CHECKSUM_UNNECESSARY;
5971 else
Eric Dumazetbc8acf22010-09-02 13:07:41 -07005972 skb_checksum_none_assert(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005973}
5974
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005975static struct sk_buff *rtl8169_try_rx_copy(void *data,
5976 struct rtl8169_private *tp,
5977 int pkt_size,
5978 dma_addr_t addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005979{
Stephen Hemmingerb4496552007-06-17 01:06:49 +02005980 struct sk_buff *skb;
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005981 struct device *d = &tp->pci_dev->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005982
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005983 data = rtl8169_align(data);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005984 dma_sync_single_for_cpu(d, addr, pkt_size, DMA_FROM_DEVICE);
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005985 prefetch(data);
5986 skb = netdev_alloc_skb_ip_align(tp->dev, pkt_size);
5987 if (skb)
5988 memcpy(skb->data, data, pkt_size);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005989 dma_sync_single_for_device(d, addr, pkt_size, DMA_FROM_DEVICE);
5990
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005991 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005992}
5993
Francois Romieuda78dbf2012-01-26 14:18:23 +01005994static int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, u32 budget)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005995{
5996 unsigned int cur_rx, rx_left;
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005997 unsigned int count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005998
Linus Torvalds1da177e2005-04-16 15:20:36 -07005999 cur_rx = tp->cur_rx;
6000 rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx;
Francois Romieu865c6522008-05-11 14:51:00 +02006001 rx_left = min(rx_left, budget);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006002
Richard Dawe4dcb7d32005-05-27 21:12:00 +02006003 for (; rx_left > 0; rx_left--, cur_rx++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006004 unsigned int entry = cur_rx % NUM_RX_DESC;
Francois Romieu126fa4b2005-05-12 20:09:17 -04006005 struct RxDesc *desc = tp->RxDescArray + entry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006006 u32 status;
6007
6008 rmb();
David S. Miller8decf862011-09-22 03:23:13 -04006009 status = le32_to_cpu(desc->opts1) & tp->opts1_mask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006010
6011 if (status & DescOwn)
6012 break;
Richard Dawe4dcb7d32005-05-27 21:12:00 +02006013 if (unlikely(status & RxRES)) {
Joe Perchesbf82c182010-02-09 11:49:50 +00006014 netif_info(tp, rx_err, dev, "Rx ERROR. status = %08x\n",
6015 status);
Francois Romieucebf8cc2007-10-18 12:06:54 +02006016 dev->stats.rx_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006017 if (status & (RxRWT | RxRUNT))
Francois Romieucebf8cc2007-10-18 12:06:54 +02006018 dev->stats.rx_length_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006019 if (status & RxCRC)
Francois Romieucebf8cc2007-10-18 12:06:54 +02006020 dev->stats.rx_crc_errors++;
Francois Romieu9dccf612006-05-14 12:31:17 +02006021 if (status & RxFOVF) {
Francois Romieuda78dbf2012-01-26 14:18:23 +01006022 rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
Francois Romieucebf8cc2007-10-18 12:06:54 +02006023 dev->stats.rx_fifo_errors++;
Francois Romieu9dccf612006-05-14 12:31:17 +02006024 }
Ben Greear6bbe0212012-02-10 15:04:33 +00006025 if ((status & (RxRUNT | RxCRC)) &&
6026 !(status & (RxRWT | RxFOVF)) &&
6027 (dev->features & NETIF_F_RXALL))
6028 goto process_pkt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006029 } else {
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006030 struct sk_buff *skb;
Ben Greear6bbe0212012-02-10 15:04:33 +00006031 dma_addr_t addr;
6032 int pkt_size;
6033
6034process_pkt:
6035 addr = le64_to_cpu(desc->addr);
Ben Greear79d0c1d2012-02-10 15:04:34 +00006036 if (likely(!(dev->features & NETIF_F_RXFCS)))
6037 pkt_size = (status & 0x00003fff) - 4;
6038 else
6039 pkt_size = status & 0x00003fff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006040
Francois Romieu126fa4b2005-05-12 20:09:17 -04006041 /*
6042 * The driver does not support incoming fragmented
6043 * frames. They are seen as a symptom of over-mtu
6044 * sized frames.
6045 */
6046 if (unlikely(rtl8169_fragmented_frame(status))) {
Francois Romieucebf8cc2007-10-18 12:06:54 +02006047 dev->stats.rx_dropped++;
6048 dev->stats.rx_length_errors++;
françois romieuce11ff52013-01-24 13:30:06 +00006049 goto release_descriptor;
Francois Romieu126fa4b2005-05-12 20:09:17 -04006050 }
6051
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006052 skb = rtl8169_try_rx_copy(tp->Rx_databuff[entry],
6053 tp, pkt_size, addr);
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006054 if (!skb) {
6055 dev->stats.rx_dropped++;
françois romieuce11ff52013-01-24 13:30:06 +00006056 goto release_descriptor;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006057 }
6058
Eric Dumazetadea1ac72010-09-05 20:04:05 -07006059 rtl8169_rx_csum(skb, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006060 skb_put(skb, pkt_size);
6061 skb->protocol = eth_type_trans(skb, dev);
6062
Francois Romieu7a8fc772011-03-01 17:18:33 +01006063 rtl8169_rx_vlan_tag(desc, skb);
6064
Francois Romieu56de4142011-03-15 17:29:31 +01006065 napi_gro_receive(&tp->napi, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006066
Junchang Wang8027aa22012-03-04 23:30:32 +01006067 u64_stats_update_begin(&tp->rx_stats.syncp);
6068 tp->rx_stats.packets++;
6069 tp->rx_stats.bytes += pkt_size;
6070 u64_stats_update_end(&tp->rx_stats.syncp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006071 }
françois romieuce11ff52013-01-24 13:30:06 +00006072release_descriptor:
6073 desc->opts2 = 0;
6074 wmb();
6075 rtl8169_mark_to_asic(desc, rx_buf_sz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006076 }
6077
6078 count = cur_rx - tp->cur_rx;
6079 tp->cur_rx = cur_rx;
6080
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006081 tp->dirty_rx += count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006082
6083 return count;
6084}
6085
Francois Romieu07d3f512007-02-21 22:40:46 +01006086static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006087{
Francois Romieu07d3f512007-02-21 22:40:46 +01006088 struct net_device *dev = dev_instance;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006089 struct rtl8169_private *tp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006090 int handled = 0;
Francois Romieu9085cdfa2012-01-26 12:59:08 +01006091 u16 status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006092
Francois Romieu9085cdfa2012-01-26 12:59:08 +01006093 status = rtl_get_events(tp);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006094 if (status && status != 0xffff) {
6095 status &= RTL_EVENT_NAPI | tp->event_slow;
6096 if (status) {
6097 handled = 1;
françois romieu811fd302011-12-04 20:30:45 +00006098
Francois Romieuda78dbf2012-01-26 14:18:23 +01006099 rtl_irq_disable(tp);
6100 napi_schedule(&tp->napi);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006101 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006102 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006103 return IRQ_RETVAL(handled);
6104}
6105
Francois Romieuda78dbf2012-01-26 14:18:23 +01006106/*
6107 * Workqueue context.
6108 */
6109static void rtl_slow_event_work(struct rtl8169_private *tp)
6110{
6111 struct net_device *dev = tp->dev;
6112 u16 status;
6113
6114 status = rtl_get_events(tp) & tp->event_slow;
6115 rtl_ack_events(tp, status);
6116
6117 if (unlikely(status & RxFIFOOver)) {
6118 switch (tp->mac_version) {
6119 /* Work around for rx fifo overflow */
6120 case RTL_GIGA_MAC_VER_11:
6121 netif_stop_queue(dev);
Francois Romieu934714d2012-01-31 11:09:21 +01006122 /* XXX - Hack alert. See rtl_task(). */
6123 set_bit(RTL_FLAG_TASK_RESET_PENDING, tp->wk.flags);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006124 default:
6125 break;
6126 }
6127 }
6128
6129 if (unlikely(status & SYSErr))
6130 rtl8169_pcierr_interrupt(dev);
6131
6132 if (status & LinkChg)
6133 __rtl8169_check_link_status(dev, tp, tp->mmio_addr, true);
6134
françois romieu7dbb4912012-06-09 10:53:16 +00006135 rtl_irq_enable_all(tp);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006136}
6137
Francois Romieu4422bcd2012-01-26 11:23:32 +01006138static void rtl_task(struct work_struct *work)
6139{
Francois Romieuda78dbf2012-01-26 14:18:23 +01006140 static const struct {
6141 int bitnr;
6142 void (*action)(struct rtl8169_private *);
6143 } rtl_work[] = {
Francois Romieu934714d2012-01-31 11:09:21 +01006144 /* XXX - keep rtl_slow_event_work() as first element. */
Francois Romieuda78dbf2012-01-26 14:18:23 +01006145 { RTL_FLAG_TASK_SLOW_PENDING, rtl_slow_event_work },
6146 { RTL_FLAG_TASK_RESET_PENDING, rtl_reset_work },
6147 { RTL_FLAG_TASK_PHY_PENDING, rtl_phy_work }
6148 };
Francois Romieu4422bcd2012-01-26 11:23:32 +01006149 struct rtl8169_private *tp =
6150 container_of(work, struct rtl8169_private, wk.work);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006151 struct net_device *dev = tp->dev;
6152 int i;
Francois Romieu4422bcd2012-01-26 11:23:32 +01006153
Francois Romieuda78dbf2012-01-26 14:18:23 +01006154 rtl_lock_work(tp);
6155
Francois Romieu6c4a70c2012-01-31 10:56:44 +01006156 if (!netif_running(dev) ||
6157 !test_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags))
Francois Romieuda78dbf2012-01-26 14:18:23 +01006158 goto out_unlock;
6159
6160 for (i = 0; i < ARRAY_SIZE(rtl_work); i++) {
6161 bool pending;
6162
Francois Romieuda78dbf2012-01-26 14:18:23 +01006163 pending = test_and_clear_bit(rtl_work[i].bitnr, tp->wk.flags);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006164 if (pending)
6165 rtl_work[i].action(tp);
6166 }
6167
6168out_unlock:
6169 rtl_unlock_work(tp);
Francois Romieu4422bcd2012-01-26 11:23:32 +01006170}
6171
Stephen Hemmingerbea33482007-10-03 16:41:36 -07006172static int rtl8169_poll(struct napi_struct *napi, int budget)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006173{
Stephen Hemmingerbea33482007-10-03 16:41:36 -07006174 struct rtl8169_private *tp = container_of(napi, struct rtl8169_private, napi);
6175 struct net_device *dev = tp->dev;
Francois Romieuda78dbf2012-01-26 14:18:23 +01006176 u16 enable_mask = RTL_EVENT_NAPI | tp->event_slow;
6177 int work_done= 0;
6178 u16 status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006179
Francois Romieuda78dbf2012-01-26 14:18:23 +01006180 status = rtl_get_events(tp);
6181 rtl_ack_events(tp, status & ~tp->event_slow);
6182
6183 if (status & RTL_EVENT_NAPI_RX)
6184 work_done = rtl_rx(dev, tp, (u32) budget);
6185
6186 if (status & RTL_EVENT_NAPI_TX)
6187 rtl_tx(dev, tp);
6188
6189 if (status & tp->event_slow) {
6190 enable_mask &= ~tp->event_slow;
6191
6192 rtl_schedule_task(tp, RTL_FLAG_TASK_SLOW_PENDING);
6193 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006194
Stephen Hemmingerbea33482007-10-03 16:41:36 -07006195 if (work_done < budget) {
Ben Hutchings288379f2009-01-19 16:43:59 -08006196 napi_complete(napi);
David Dillowf11a3772009-05-22 15:29:34 +00006197
Francois Romieuda78dbf2012-01-26 14:18:23 +01006198 rtl_irq_enable(tp, enable_mask);
6199 mmiowb();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006200 }
6201
Stephen Hemmingerbea33482007-10-03 16:41:36 -07006202 return work_done;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006203}
Linus Torvalds1da177e2005-04-16 15:20:36 -07006204
Francois Romieu523a6092008-09-10 22:28:56 +02006205static void rtl8169_rx_missed(struct net_device *dev, void __iomem *ioaddr)
6206{
6207 struct rtl8169_private *tp = netdev_priv(dev);
6208
6209 if (tp->mac_version > RTL_GIGA_MAC_VER_06)
6210 return;
6211
6212 dev->stats.rx_missed_errors += (RTL_R32(RxMissed) & 0xffffff);
6213 RTL_W32(RxMissed, 0);
6214}
6215
Linus Torvalds1da177e2005-04-16 15:20:36 -07006216static void rtl8169_down(struct net_device *dev)
6217{
6218 struct rtl8169_private *tp = netdev_priv(dev);
6219 void __iomem *ioaddr = tp->mmio_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006220
Francois Romieu4876cc12011-03-11 21:07:11 +01006221 del_timer_sync(&tp->timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006222
Stephen Hemminger93dd79e2007-10-28 17:14:06 +01006223 napi_disable(&tp->napi);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006224 netif_stop_queue(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006225
Hayes Wang92fc43b2011-07-06 15:58:03 +08006226 rtl8169_hw_reset(tp);
Stanislaw Gruszka323bb682010-10-20 22:25:41 +00006227 /*
6228 * At this point device interrupts can not be enabled in any function,
Francois Romieu209e5ac2012-01-26 09:59:50 +01006229 * as netif_running is not true (rtl8169_interrupt, rtl8169_reset_task)
6230 * and napi is disabled (rtl8169_poll).
Stanislaw Gruszka323bb682010-10-20 22:25:41 +00006231 */
Francois Romieu523a6092008-09-10 22:28:56 +02006232 rtl8169_rx_missed(dev, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006233
Linus Torvalds1da177e2005-04-16 15:20:36 -07006234 /* Give a racing hard_start_xmit a few cycles to complete. */
Francois Romieuda78dbf2012-01-26 14:18:23 +01006235 synchronize_sched();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006236
Linus Torvalds1da177e2005-04-16 15:20:36 -07006237 rtl8169_tx_clear(tp);
6238
6239 rtl8169_rx_clear(tp);
françois romieu065c27c2011-01-03 15:08:12 +00006240
6241 rtl_pll_power_down(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006242}
6243
6244static int rtl8169_close(struct net_device *dev)
6245{
6246 struct rtl8169_private *tp = netdev_priv(dev);
6247 struct pci_dev *pdev = tp->pci_dev;
6248
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006249 pm_runtime_get_sync(&pdev->dev);
6250
Francois Romieucecb5fd2011-04-01 10:21:07 +02006251 /* Update counters before going down */
Ivan Vecera355423d2009-02-06 21:49:57 -08006252 rtl8169_update_counters(dev);
6253
Francois Romieuda78dbf2012-01-26 14:18:23 +01006254 rtl_lock_work(tp);
Francois Romieu6c4a70c2012-01-31 10:56:44 +01006255 clear_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006256
Linus Torvalds1da177e2005-04-16 15:20:36 -07006257 rtl8169_down(dev);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006258 rtl_unlock_work(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006259
Francois Romieu92a7c4e2012-03-10 10:42:12 +01006260 free_irq(pdev->irq, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006261
Stanislaw Gruszka82553bb2010-10-08 04:25:01 +00006262 dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray,
6263 tp->RxPhyAddr);
6264 dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray,
6265 tp->TxPhyAddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006266 tp->TxDescArray = NULL;
6267 tp->RxDescArray = NULL;
6268
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006269 pm_runtime_put_sync(&pdev->dev);
6270
Linus Torvalds1da177e2005-04-16 15:20:36 -07006271 return 0;
6272}
6273
Francois Romieudc1c00c2012-03-08 10:06:18 +01006274#ifdef CONFIG_NET_POLL_CONTROLLER
6275static void rtl8169_netpoll(struct net_device *dev)
6276{
6277 struct rtl8169_private *tp = netdev_priv(dev);
6278
6279 rtl8169_interrupt(tp->pci_dev->irq, dev);
6280}
6281#endif
6282
Francois Romieudf43ac72012-03-08 09:48:40 +01006283static int rtl_open(struct net_device *dev)
6284{
6285 struct rtl8169_private *tp = netdev_priv(dev);
6286 void __iomem *ioaddr = tp->mmio_addr;
6287 struct pci_dev *pdev = tp->pci_dev;
6288 int retval = -ENOMEM;
6289
6290 pm_runtime_get_sync(&pdev->dev);
6291
6292 /*
Jiri Kosinae75d6602012-04-08 21:48:52 +02006293 * Rx and Tx descriptors needs 256 bytes alignment.
Francois Romieudf43ac72012-03-08 09:48:40 +01006294 * dma_alloc_coherent provides more.
6295 */
6296 tp->TxDescArray = dma_alloc_coherent(&pdev->dev, R8169_TX_RING_BYTES,
6297 &tp->TxPhyAddr, GFP_KERNEL);
6298 if (!tp->TxDescArray)
6299 goto err_pm_runtime_put;
6300
6301 tp->RxDescArray = dma_alloc_coherent(&pdev->dev, R8169_RX_RING_BYTES,
6302 &tp->RxPhyAddr, GFP_KERNEL);
6303 if (!tp->RxDescArray)
6304 goto err_free_tx_0;
6305
6306 retval = rtl8169_init_ring(dev);
6307 if (retval < 0)
6308 goto err_free_rx_1;
6309
6310 INIT_WORK(&tp->wk.work, rtl_task);
6311
6312 smp_mb();
6313
6314 rtl_request_firmware(tp);
6315
Francois Romieu92a7c4e2012-03-10 10:42:12 +01006316 retval = request_irq(pdev->irq, rtl8169_interrupt,
Francois Romieudf43ac72012-03-08 09:48:40 +01006317 (tp->features & RTL_FEATURE_MSI) ? 0 : IRQF_SHARED,
6318 dev->name, dev);
6319 if (retval < 0)
6320 goto err_release_fw_2;
6321
6322 rtl_lock_work(tp);
6323
6324 set_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
6325
6326 napi_enable(&tp->napi);
6327
6328 rtl8169_init_phy(dev, tp);
6329
6330 __rtl8169_set_features(dev, dev->features);
6331
6332 rtl_pll_power_up(tp);
6333
6334 rtl_hw_start(dev);
6335
6336 netif_start_queue(dev);
6337
6338 rtl_unlock_work(tp);
6339
6340 tp->saved_wolopts = 0;
6341 pm_runtime_put_noidle(&pdev->dev);
6342
6343 rtl8169_check_link_status(dev, tp, ioaddr);
6344out:
6345 return retval;
6346
6347err_release_fw_2:
6348 rtl_release_firmware(tp);
6349 rtl8169_rx_clear(tp);
6350err_free_rx_1:
6351 dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray,
6352 tp->RxPhyAddr);
6353 tp->RxDescArray = NULL;
6354err_free_tx_0:
6355 dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray,
6356 tp->TxPhyAddr);
6357 tp->TxDescArray = NULL;
6358err_pm_runtime_put:
6359 pm_runtime_put_noidle(&pdev->dev);
6360 goto out;
6361}
6362
Junchang Wang8027aa22012-03-04 23:30:32 +01006363static struct rtnl_link_stats64 *
6364rtl8169_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006365{
6366 struct rtl8169_private *tp = netdev_priv(dev);
6367 void __iomem *ioaddr = tp->mmio_addr;
Junchang Wang8027aa22012-03-04 23:30:32 +01006368 unsigned int start;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006369
Francois Romieuda78dbf2012-01-26 14:18:23 +01006370 if (netif_running(dev))
Francois Romieu523a6092008-09-10 22:28:56 +02006371 rtl8169_rx_missed(dev, ioaddr);
Francois Romieu5b0384f2006-08-16 16:00:01 +02006372
Junchang Wang8027aa22012-03-04 23:30:32 +01006373 do {
6374 start = u64_stats_fetch_begin_bh(&tp->rx_stats.syncp);
6375 stats->rx_packets = tp->rx_stats.packets;
6376 stats->rx_bytes = tp->rx_stats.bytes;
6377 } while (u64_stats_fetch_retry_bh(&tp->rx_stats.syncp, start));
6378
6379
6380 do {
6381 start = u64_stats_fetch_begin_bh(&tp->tx_stats.syncp);
6382 stats->tx_packets = tp->tx_stats.packets;
6383 stats->tx_bytes = tp->tx_stats.bytes;
6384 } while (u64_stats_fetch_retry_bh(&tp->tx_stats.syncp, start));
6385
6386 stats->rx_dropped = dev->stats.rx_dropped;
6387 stats->tx_dropped = dev->stats.tx_dropped;
6388 stats->rx_length_errors = dev->stats.rx_length_errors;
6389 stats->rx_errors = dev->stats.rx_errors;
6390 stats->rx_crc_errors = dev->stats.rx_crc_errors;
6391 stats->rx_fifo_errors = dev->stats.rx_fifo_errors;
6392 stats->rx_missed_errors = dev->stats.rx_missed_errors;
6393
6394 return stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006395}
6396
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006397static void rtl8169_net_suspend(struct net_device *dev)
Francois Romieu5d06a992006-02-23 00:47:58 +01006398{
françois romieu065c27c2011-01-03 15:08:12 +00006399 struct rtl8169_private *tp = netdev_priv(dev);
6400
Francois Romieu5d06a992006-02-23 00:47:58 +01006401 if (!netif_running(dev))
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006402 return;
Francois Romieu5d06a992006-02-23 00:47:58 +01006403
6404 netif_device_detach(dev);
6405 netif_stop_queue(dev);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006406
6407 rtl_lock_work(tp);
6408 napi_disable(&tp->napi);
Francois Romieu6c4a70c2012-01-31 10:56:44 +01006409 clear_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006410 rtl_unlock_work(tp);
6411
6412 rtl_pll_power_down(tp);
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006413}
Francois Romieu5d06a992006-02-23 00:47:58 +01006414
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006415#ifdef CONFIG_PM
6416
6417static int rtl8169_suspend(struct device *device)
6418{
6419 struct pci_dev *pdev = to_pci_dev(device);
6420 struct net_device *dev = pci_get_drvdata(pdev);
6421
6422 rtl8169_net_suspend(dev);
Francois Romieu1371fa62007-04-02 23:01:11 +02006423
Francois Romieu5d06a992006-02-23 00:47:58 +01006424 return 0;
6425}
6426
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006427static void __rtl8169_resume(struct net_device *dev)
6428{
françois romieu065c27c2011-01-03 15:08:12 +00006429 struct rtl8169_private *tp = netdev_priv(dev);
6430
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006431 netif_device_attach(dev);
françois romieu065c27c2011-01-03 15:08:12 +00006432
6433 rtl_pll_power_up(tp);
6434
Artem Savkovcff4c162012-04-03 10:29:11 +00006435 rtl_lock_work(tp);
6436 napi_enable(&tp->napi);
Francois Romieu6c4a70c2012-01-31 10:56:44 +01006437 set_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
Artem Savkovcff4c162012-04-03 10:29:11 +00006438 rtl_unlock_work(tp);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006439
Francois Romieu98ddf982012-01-31 10:47:34 +01006440 rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006441}
6442
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006443static int rtl8169_resume(struct device *device)
Francois Romieu5d06a992006-02-23 00:47:58 +01006444{
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006445 struct pci_dev *pdev = to_pci_dev(device);
Francois Romieu5d06a992006-02-23 00:47:58 +01006446 struct net_device *dev = pci_get_drvdata(pdev);
Stanislaw Gruszkafccec102010-10-20 22:25:42 +00006447 struct rtl8169_private *tp = netdev_priv(dev);
6448
6449 rtl8169_init_phy(dev, tp);
Francois Romieu5d06a992006-02-23 00:47:58 +01006450
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006451 if (netif_running(dev))
6452 __rtl8169_resume(dev);
Francois Romieu5d06a992006-02-23 00:47:58 +01006453
Francois Romieu5d06a992006-02-23 00:47:58 +01006454 return 0;
6455}
6456
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006457static int rtl8169_runtime_suspend(struct device *device)
6458{
6459 struct pci_dev *pdev = to_pci_dev(device);
6460 struct net_device *dev = pci_get_drvdata(pdev);
6461 struct rtl8169_private *tp = netdev_priv(dev);
6462
6463 if (!tp->TxDescArray)
6464 return 0;
6465
Francois Romieuda78dbf2012-01-26 14:18:23 +01006466 rtl_lock_work(tp);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006467 tp->saved_wolopts = __rtl8169_get_wol(tp);
6468 __rtl8169_set_wol(tp, WAKE_ANY);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006469 rtl_unlock_work(tp);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006470
6471 rtl8169_net_suspend(dev);
6472
6473 return 0;
6474}
6475
6476static int rtl8169_runtime_resume(struct device *device)
6477{
6478 struct pci_dev *pdev = to_pci_dev(device);
6479 struct net_device *dev = pci_get_drvdata(pdev);
6480 struct rtl8169_private *tp = netdev_priv(dev);
6481
6482 if (!tp->TxDescArray)
6483 return 0;
6484
Francois Romieuda78dbf2012-01-26 14:18:23 +01006485 rtl_lock_work(tp);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006486 __rtl8169_set_wol(tp, tp->saved_wolopts);
6487 tp->saved_wolopts = 0;
Francois Romieuda78dbf2012-01-26 14:18:23 +01006488 rtl_unlock_work(tp);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006489
Stanislaw Gruszkafccec102010-10-20 22:25:42 +00006490 rtl8169_init_phy(dev, tp);
6491
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006492 __rtl8169_resume(dev);
6493
6494 return 0;
6495}
6496
6497static int rtl8169_runtime_idle(struct device *device)
6498{
6499 struct pci_dev *pdev = to_pci_dev(device);
6500 struct net_device *dev = pci_get_drvdata(pdev);
6501 struct rtl8169_private *tp = netdev_priv(dev);
6502
Rafael J. Wysockie4fbce72010-12-08 15:32:14 +00006503 return tp->TxDescArray ? -EBUSY : 0;
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006504}
6505
Alexey Dobriyan47145212009-12-14 18:00:08 -08006506static const struct dev_pm_ops rtl8169_pm_ops = {
Francois Romieucecb5fd2011-04-01 10:21:07 +02006507 .suspend = rtl8169_suspend,
6508 .resume = rtl8169_resume,
6509 .freeze = rtl8169_suspend,
6510 .thaw = rtl8169_resume,
6511 .poweroff = rtl8169_suspend,
6512 .restore = rtl8169_resume,
6513 .runtime_suspend = rtl8169_runtime_suspend,
6514 .runtime_resume = rtl8169_runtime_resume,
6515 .runtime_idle = rtl8169_runtime_idle,
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006516};
6517
6518#define RTL8169_PM_OPS (&rtl8169_pm_ops)
6519
6520#else /* !CONFIG_PM */
6521
6522#define RTL8169_PM_OPS NULL
6523
6524#endif /* !CONFIG_PM */
6525
David S. Miller1805b2f2011-10-24 18:18:09 -04006526static void rtl_wol_shutdown_quirk(struct rtl8169_private *tp)
6527{
6528 void __iomem *ioaddr = tp->mmio_addr;
6529
6530 /* WoL fails with 8168b when the receiver is disabled. */
6531 switch (tp->mac_version) {
6532 case RTL_GIGA_MAC_VER_11:
6533 case RTL_GIGA_MAC_VER_12:
6534 case RTL_GIGA_MAC_VER_17:
6535 pci_clear_master(tp->pci_dev);
6536
6537 RTL_W8(ChipCmd, CmdRxEnb);
6538 /* PCI commit */
6539 RTL_R8(ChipCmd);
6540 break;
6541 default:
6542 break;
6543 }
6544}
6545
Francois Romieu1765f952008-09-13 17:21:40 +02006546static void rtl_shutdown(struct pci_dev *pdev)
6547{
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006548 struct net_device *dev = pci_get_drvdata(pdev);
françois romieu4bb3f522009-06-17 11:41:45 +00006549 struct rtl8169_private *tp = netdev_priv(dev);
françois romieu2a15cd22012-03-06 01:14:12 +00006550 struct device *d = &pdev->dev;
6551
6552 pm_runtime_get_sync(d);
Francois Romieu1765f952008-09-13 17:21:40 +02006553
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006554 rtl8169_net_suspend(dev);
6555
Francois Romieucecb5fd2011-04-01 10:21:07 +02006556 /* Restore original MAC address */
Ivan Veceracc098dc2009-11-29 23:12:52 -08006557 rtl_rar_set(tp, dev->perm_addr);
6558
Hayes Wang92fc43b2011-07-06 15:58:03 +08006559 rtl8169_hw_reset(tp);
françois romieu4bb3f522009-06-17 11:41:45 +00006560
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006561 if (system_state == SYSTEM_POWER_OFF) {
David S. Miller1805b2f2011-10-24 18:18:09 -04006562 if (__rtl8169_get_wol(tp) & WAKE_ANY) {
6563 rtl_wol_suspend_quirk(tp);
6564 rtl_wol_shutdown_quirk(tp);
françois romieuca52efd2009-07-24 12:34:19 +00006565 }
6566
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006567 pci_wake_from_d3(pdev, true);
6568 pci_set_power_state(pdev, PCI_D3hot);
6569 }
françois romieu2a15cd22012-03-06 01:14:12 +00006570
6571 pm_runtime_put_noidle(d);
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006572}
Francois Romieu5d06a992006-02-23 00:47:58 +01006573
Bill Pembertonbaf63292012-12-03 09:23:28 -05006574static void rtl_remove_one(struct pci_dev *pdev)
Francois Romieue27566e2012-03-08 09:54:01 +01006575{
6576 struct net_device *dev = pci_get_drvdata(pdev);
6577 struct rtl8169_private *tp = netdev_priv(dev);
6578
6579 if (tp->mac_version == RTL_GIGA_MAC_VER_27 ||
6580 tp->mac_version == RTL_GIGA_MAC_VER_28 ||
6581 tp->mac_version == RTL_GIGA_MAC_VER_31) {
6582 rtl8168_driver_stop(tp);
6583 }
6584
6585 cancel_work_sync(&tp->wk.work);
6586
Devendra Nagaad1be8d2012-05-31 01:51:20 +00006587 netif_napi_del(&tp->napi);
6588
Francois Romieue27566e2012-03-08 09:54:01 +01006589 unregister_netdev(dev);
6590
6591 rtl_release_firmware(tp);
6592
6593 if (pci_dev_run_wake(pdev))
6594 pm_runtime_get_noresume(&pdev->dev);
6595
6596 /* restore original MAC address */
6597 rtl_rar_set(tp, dev->perm_addr);
6598
6599 rtl_disable_msi(pdev, tp);
6600 rtl8169_release_board(pdev, dev, tp->mmio_addr);
6601 pci_set_drvdata(pdev, NULL);
6602}
6603
Francois Romieufa9c3852012-03-08 10:01:50 +01006604static const struct net_device_ops rtl_netdev_ops = {
Francois Romieudf43ac72012-03-08 09:48:40 +01006605 .ndo_open = rtl_open,
Francois Romieufa9c3852012-03-08 10:01:50 +01006606 .ndo_stop = rtl8169_close,
6607 .ndo_get_stats64 = rtl8169_get_stats64,
6608 .ndo_start_xmit = rtl8169_start_xmit,
6609 .ndo_tx_timeout = rtl8169_tx_timeout,
6610 .ndo_validate_addr = eth_validate_addr,
6611 .ndo_change_mtu = rtl8169_change_mtu,
6612 .ndo_fix_features = rtl8169_fix_features,
6613 .ndo_set_features = rtl8169_set_features,
6614 .ndo_set_mac_address = rtl_set_mac_address,
6615 .ndo_do_ioctl = rtl8169_ioctl,
6616 .ndo_set_rx_mode = rtl_set_rx_mode,
6617#ifdef CONFIG_NET_POLL_CONTROLLER
6618 .ndo_poll_controller = rtl8169_netpoll,
6619#endif
6620
6621};
6622
Francois Romieu31fa8b12012-03-08 10:09:40 +01006623static const struct rtl_cfg_info {
6624 void (*hw_start)(struct net_device *);
6625 unsigned int region;
6626 unsigned int align;
6627 u16 event_slow;
6628 unsigned features;
6629 u8 default_ver;
6630} rtl_cfg_infos [] = {
6631 [RTL_CFG_0] = {
6632 .hw_start = rtl_hw_start_8169,
6633 .region = 1,
6634 .align = 0,
6635 .event_slow = SYSErr | LinkChg | RxOverflow | RxFIFOOver,
6636 .features = RTL_FEATURE_GMII,
6637 .default_ver = RTL_GIGA_MAC_VER_01,
6638 },
6639 [RTL_CFG_1] = {
6640 .hw_start = rtl_hw_start_8168,
6641 .region = 2,
6642 .align = 8,
6643 .event_slow = SYSErr | LinkChg | RxOverflow,
6644 .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI,
6645 .default_ver = RTL_GIGA_MAC_VER_11,
6646 },
6647 [RTL_CFG_2] = {
6648 .hw_start = rtl_hw_start_8101,
6649 .region = 2,
6650 .align = 8,
6651 .event_slow = SYSErr | LinkChg | RxOverflow | RxFIFOOver |
6652 PCSTimeout,
6653 .features = RTL_FEATURE_MSI,
6654 .default_ver = RTL_GIGA_MAC_VER_13,
6655 }
6656};
6657
6658/* Cfg9346_Unlock assumed. */
6659static unsigned rtl_try_msi(struct rtl8169_private *tp,
6660 const struct rtl_cfg_info *cfg)
6661{
6662 void __iomem *ioaddr = tp->mmio_addr;
6663 unsigned msi = 0;
6664 u8 cfg2;
6665
6666 cfg2 = RTL_R8(Config2) & ~MSIEnable;
6667 if (cfg->features & RTL_FEATURE_MSI) {
6668 if (pci_enable_msi(tp->pci_dev)) {
6669 netif_info(tp, hw, tp->dev, "no MSI. Back to INTx.\n");
6670 } else {
6671 cfg2 |= MSIEnable;
6672 msi = RTL_FEATURE_MSI;
6673 }
6674 }
6675 if (tp->mac_version <= RTL_GIGA_MAC_VER_06)
6676 RTL_W8(Config2, cfg2);
6677 return msi;
6678}
6679
Hayes Wangc5583862012-07-02 17:23:22 +08006680DECLARE_RTL_COND(rtl_link_list_ready_cond)
6681{
6682 void __iomem *ioaddr = tp->mmio_addr;
6683
6684 return RTL_R8(MCU) & LINK_LIST_RDY;
6685}
6686
6687DECLARE_RTL_COND(rtl_rxtx_empty_cond)
6688{
6689 void __iomem *ioaddr = tp->mmio_addr;
6690
6691 return (RTL_R8(MCU) & RXTX_EMPTY) == RXTX_EMPTY;
6692}
6693
Bill Pembertonbaf63292012-12-03 09:23:28 -05006694static void rtl_hw_init_8168g(struct rtl8169_private *tp)
Hayes Wangc5583862012-07-02 17:23:22 +08006695{
6696 void __iomem *ioaddr = tp->mmio_addr;
6697 u32 data;
6698
6699 tp->ocp_base = OCP_STD_PHY_BASE;
6700
6701 RTL_W32(MISC, RTL_R32(MISC) | RXDV_GATED_EN);
6702
6703 if (!rtl_udelay_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 42))
6704 return;
6705
6706 if (!rtl_udelay_loop_wait_high(tp, &rtl_rxtx_empty_cond, 100, 42))
6707 return;
6708
6709 RTL_W8(ChipCmd, RTL_R8(ChipCmd) & ~(CmdTxEnb | CmdRxEnb));
6710 msleep(1);
6711 RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
6712
Hayes Wang5f8bcce2012-07-10 08:47:05 +02006713 data = r8168_mac_ocp_read(tp, 0xe8de);
Hayes Wangc5583862012-07-02 17:23:22 +08006714 data &= ~(1 << 14);
6715 r8168_mac_ocp_write(tp, 0xe8de, data);
6716
6717 if (!rtl_udelay_loop_wait_high(tp, &rtl_link_list_ready_cond, 100, 42))
6718 return;
6719
Hayes Wang5f8bcce2012-07-10 08:47:05 +02006720 data = r8168_mac_ocp_read(tp, 0xe8de);
Hayes Wangc5583862012-07-02 17:23:22 +08006721 data |= (1 << 15);
6722 r8168_mac_ocp_write(tp, 0xe8de, data);
6723
6724 if (!rtl_udelay_loop_wait_high(tp, &rtl_link_list_ready_cond, 100, 42))
6725 return;
6726}
6727
Bill Pembertonbaf63292012-12-03 09:23:28 -05006728static void rtl_hw_initialize(struct rtl8169_private *tp)
Hayes Wangc5583862012-07-02 17:23:22 +08006729{
6730 switch (tp->mac_version) {
6731 case RTL_GIGA_MAC_VER_40:
6732 case RTL_GIGA_MAC_VER_41:
6733 rtl_hw_init_8168g(tp);
6734 break;
6735
6736 default:
6737 break;
6738 }
6739}
6740
Bill Pembertonbaf63292012-12-03 09:23:28 -05006741static int
Francois Romieu3b6cf252012-03-08 09:59:04 +01006742rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
6743{
6744 const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data;
6745 const unsigned int region = cfg->region;
6746 struct rtl8169_private *tp;
6747 struct mii_if_info *mii;
6748 struct net_device *dev;
6749 void __iomem *ioaddr;
6750 int chipset, i;
6751 int rc;
6752
6753 if (netif_msg_drv(&debug)) {
6754 printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n",
6755 MODULENAME, RTL8169_VERSION);
6756 }
6757
6758 dev = alloc_etherdev(sizeof (*tp));
6759 if (!dev) {
6760 rc = -ENOMEM;
6761 goto out;
6762 }
6763
6764 SET_NETDEV_DEV(dev, &pdev->dev);
Francois Romieufa9c3852012-03-08 10:01:50 +01006765 dev->netdev_ops = &rtl_netdev_ops;
Francois Romieu3b6cf252012-03-08 09:59:04 +01006766 tp = netdev_priv(dev);
6767 tp->dev = dev;
6768 tp->pci_dev = pdev;
6769 tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT);
6770
6771 mii = &tp->mii;
6772 mii->dev = dev;
6773 mii->mdio_read = rtl_mdio_read;
6774 mii->mdio_write = rtl_mdio_write;
6775 mii->phy_id_mask = 0x1f;
6776 mii->reg_num_mask = 0x1f;
6777 mii->supports_gmii = !!(cfg->features & RTL_FEATURE_GMII);
6778
6779 /* disable ASPM completely as that cause random device stop working
6780 * problems as well as full system hangs for some PCIe devices users */
6781 pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
6782 PCIE_LINK_STATE_CLKPM);
6783
6784 /* enable device (incl. PCI PM wakeup and hotplug setup) */
6785 rc = pci_enable_device(pdev);
6786 if (rc < 0) {
6787 netif_err(tp, probe, dev, "enable failure\n");
6788 goto err_out_free_dev_1;
6789 }
6790
6791 if (pci_set_mwi(pdev) < 0)
6792 netif_info(tp, probe, dev, "Mem-Wr-Inval unavailable\n");
6793
6794 /* make sure PCI base addr 1 is MMIO */
6795 if (!(pci_resource_flags(pdev, region) & IORESOURCE_MEM)) {
6796 netif_err(tp, probe, dev,
6797 "region #%d not an MMIO resource, aborting\n",
6798 region);
6799 rc = -ENODEV;
6800 goto err_out_mwi_2;
6801 }
6802
6803 /* check for weird/broken PCI region reporting */
6804 if (pci_resource_len(pdev, region) < R8169_REGS_SIZE) {
6805 netif_err(tp, probe, dev,
6806 "Invalid PCI region size(s), aborting\n");
6807 rc = -ENODEV;
6808 goto err_out_mwi_2;
6809 }
6810
6811 rc = pci_request_regions(pdev, MODULENAME);
6812 if (rc < 0) {
6813 netif_err(tp, probe, dev, "could not request regions\n");
6814 goto err_out_mwi_2;
6815 }
6816
6817 tp->cp_cmd = RxChkSum;
6818
6819 if ((sizeof(dma_addr_t) > 4) &&
6820 !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && use_dac) {
6821 tp->cp_cmd |= PCIDAC;
6822 dev->features |= NETIF_F_HIGHDMA;
6823 } else {
6824 rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
6825 if (rc < 0) {
6826 netif_err(tp, probe, dev, "DMA configuration failed\n");
6827 goto err_out_free_res_3;
6828 }
6829 }
6830
6831 /* ioremap MMIO region */
6832 ioaddr = ioremap(pci_resource_start(pdev, region), R8169_REGS_SIZE);
6833 if (!ioaddr) {
6834 netif_err(tp, probe, dev, "cannot remap MMIO, aborting\n");
6835 rc = -EIO;
6836 goto err_out_free_res_3;
6837 }
6838 tp->mmio_addr = ioaddr;
6839
6840 if (!pci_is_pcie(pdev))
6841 netif_info(tp, probe, dev, "not PCI Express\n");
6842
6843 /* Identify chip attached to board */
6844 rtl8169_get_mac_version(tp, dev, cfg->default_ver);
6845
6846 rtl_init_rxcfg(tp);
6847
6848 rtl_irq_disable(tp);
6849
Hayes Wangc5583862012-07-02 17:23:22 +08006850 rtl_hw_initialize(tp);
6851
Francois Romieu3b6cf252012-03-08 09:59:04 +01006852 rtl_hw_reset(tp);
6853
6854 rtl_ack_events(tp, 0xffff);
6855
6856 pci_set_master(pdev);
6857
6858 /*
6859 * Pretend we are using VLANs; This bypasses a nasty bug where
6860 * Interrupts stop flowing on high load on 8110SCd controllers.
6861 */
6862 if (tp->mac_version == RTL_GIGA_MAC_VER_05)
6863 tp->cp_cmd |= RxVlan;
6864
6865 rtl_init_mdio_ops(tp);
6866 rtl_init_pll_power_ops(tp);
6867 rtl_init_jumbo_ops(tp);
Hayes Wangbeb1fe12012-03-30 14:33:01 +08006868 rtl_init_csi_ops(tp);
Francois Romieu3b6cf252012-03-08 09:59:04 +01006869
6870 rtl8169_print_mac_version(tp);
6871
6872 chipset = tp->mac_version;
6873 tp->txd_version = rtl_chip_infos[chipset].txd_version;
6874
6875 RTL_W8(Cfg9346, Cfg9346_Unlock);
6876 RTL_W8(Config1, RTL_R8(Config1) | PMEnable);
6877 RTL_W8(Config5, RTL_R8(Config5) & PMEStatus);
6878 if ((RTL_R8(Config3) & (LinkUp | MagicPacket)) != 0)
6879 tp->features |= RTL_FEATURE_WOL;
6880 if ((RTL_R8(Config5) & (UWF | BWF | MWF)) != 0)
6881 tp->features |= RTL_FEATURE_WOL;
6882 tp->features |= rtl_try_msi(tp, cfg);
6883 RTL_W8(Cfg9346, Cfg9346_Lock);
6884
6885 if (rtl_tbi_enabled(tp)) {
6886 tp->set_speed = rtl8169_set_speed_tbi;
6887 tp->get_settings = rtl8169_gset_tbi;
6888 tp->phy_reset_enable = rtl8169_tbi_reset_enable;
6889 tp->phy_reset_pending = rtl8169_tbi_reset_pending;
6890 tp->link_ok = rtl8169_tbi_link_ok;
6891 tp->do_ioctl = rtl_tbi_ioctl;
6892 } else {
6893 tp->set_speed = rtl8169_set_speed_xmii;
6894 tp->get_settings = rtl8169_gset_xmii;
6895 tp->phy_reset_enable = rtl8169_xmii_reset_enable;
6896 tp->phy_reset_pending = rtl8169_xmii_reset_pending;
6897 tp->link_ok = rtl8169_xmii_link_ok;
6898 tp->do_ioctl = rtl_xmii_ioctl;
6899 }
6900
6901 mutex_init(&tp->wk.mutex);
6902
6903 /* Get MAC address */
6904 for (i = 0; i < ETH_ALEN; i++)
6905 dev->dev_addr[i] = RTL_R8(MAC0 + i);
6906 memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
6907
6908 SET_ETHTOOL_OPS(dev, &rtl8169_ethtool_ops);
6909 dev->watchdog_timeo = RTL8169_TX_TIMEOUT;
Francois Romieu3b6cf252012-03-08 09:59:04 +01006910
6911 netif_napi_add(dev, &tp->napi, rtl8169_poll, R8169_NAPI_WEIGHT);
6912
6913 /* don't enable SG, IP_CSUM and TSO by default - it might not work
6914 * properly for all devices */
6915 dev->features |= NETIF_F_RXCSUM |
6916 NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
6917
6918 dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
6919 NETIF_F_RXCSUM | NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
6920 dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
6921 NETIF_F_HIGHDMA;
6922
6923 if (tp->mac_version == RTL_GIGA_MAC_VER_05)
6924 /* 8110SCd requires hardware Rx VLAN - disallow toggling */
6925 dev->hw_features &= ~NETIF_F_HW_VLAN_RX;
6926
6927 dev->hw_features |= NETIF_F_RXALL;
6928 dev->hw_features |= NETIF_F_RXFCS;
6929
6930 tp->hw_start = cfg->hw_start;
6931 tp->event_slow = cfg->event_slow;
6932
6933 tp->opts1_mask = (tp->mac_version != RTL_GIGA_MAC_VER_01) ?
6934 ~(RxBOVF | RxFOVF) : ~0;
6935
6936 init_timer(&tp->timer);
6937 tp->timer.data = (unsigned long) dev;
6938 tp->timer.function = rtl8169_phy_timer;
6939
6940 tp->rtl_fw = RTL_FIRMWARE_UNKNOWN;
6941
6942 rc = register_netdev(dev);
6943 if (rc < 0)
6944 goto err_out_msi_4;
6945
6946 pci_set_drvdata(pdev, dev);
6947
Francois Romieu92a7c4e2012-03-10 10:42:12 +01006948 netif_info(tp, probe, dev, "%s at 0x%p, %pM, XID %08x IRQ %d\n",
6949 rtl_chip_infos[chipset].name, ioaddr, dev->dev_addr,
6950 (u32)(RTL_R32(TxConfig) & 0x9cf0f8ff), pdev->irq);
Francois Romieu3b6cf252012-03-08 09:59:04 +01006951 if (rtl_chip_infos[chipset].jumbo_max != JUMBO_1K) {
6952 netif_info(tp, probe, dev, "jumbo features [frames: %d bytes, "
6953 "tx checksumming: %s]\n",
6954 rtl_chip_infos[chipset].jumbo_max,
6955 rtl_chip_infos[chipset].jumbo_tx_csum ? "ok" : "ko");
6956 }
6957
6958 if (tp->mac_version == RTL_GIGA_MAC_VER_27 ||
6959 tp->mac_version == RTL_GIGA_MAC_VER_28 ||
6960 tp->mac_version == RTL_GIGA_MAC_VER_31) {
6961 rtl8168_driver_start(tp);
6962 }
6963
6964 device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL);
6965
6966 if (pci_dev_run_wake(pdev))
6967 pm_runtime_put_noidle(&pdev->dev);
6968
6969 netif_carrier_off(dev);
6970
6971out:
6972 return rc;
6973
6974err_out_msi_4:
Devendra Nagaad1be8d2012-05-31 01:51:20 +00006975 netif_napi_del(&tp->napi);
Francois Romieu3b6cf252012-03-08 09:59:04 +01006976 rtl_disable_msi(pdev, tp);
6977 iounmap(ioaddr);
6978err_out_free_res_3:
6979 pci_release_regions(pdev);
6980err_out_mwi_2:
6981 pci_clear_mwi(pdev);
6982 pci_disable_device(pdev);
6983err_out_free_dev_1:
6984 free_netdev(dev);
6985 goto out;
6986}
6987
Linus Torvalds1da177e2005-04-16 15:20:36 -07006988static struct pci_driver rtl8169_pci_driver = {
6989 .name = MODULENAME,
6990 .id_table = rtl8169_pci_tbl,
Francois Romieu3b6cf252012-03-08 09:59:04 +01006991 .probe = rtl_init_one,
Bill Pembertonbaf63292012-12-03 09:23:28 -05006992 .remove = rtl_remove_one,
Francois Romieu1765f952008-09-13 17:21:40 +02006993 .shutdown = rtl_shutdown,
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006994 .driver.pm = RTL8169_PM_OPS,
Linus Torvalds1da177e2005-04-16 15:20:36 -07006995};
6996
Devendra Naga3eeb7da2012-10-26 09:27:42 +00006997module_pci_driver(rtl8169_pci_driver);