blob: 28fb50a1e9c350851b3844592bf85adea877f604 [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 Romieuf0e837d92005-09-30 16:54:02 -070066 (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN)
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +020067
Julien Ducourthial477206a2012-05-09 00:00:06 +020068#define TX_SLOTS_AVAIL(tp) \
69 (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx)
70
71/* A skbuff with nr_frags needs nr_frags+1 entries in the tx queue */
72#define TX_FRAGS_READY_FOR(tp,nr_frags) \
73 (TX_SLOTS_AVAIL(tp) >= (nr_frags + 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -070074
Linus Torvalds1da177e2005-04-16 15:20:36 -070075/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
76 The RTL chips use a 64 element hash table based on the Ethernet CRC. */
Arjan van de Venf71e1302006-03-03 21:33:57 -050077static const int multicast_filter_limit = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -070078
Francois Romieu9c14cea2008-07-05 00:21:15 +020079#define MAX_READ_REQUEST_SHIFT 12
Michal Schmidtaee77e42012-09-09 13:55:26 +000080#define TX_DMA_BURST 7 /* Maximum PCI burst, '7' is unlimited */
Linus Torvalds1da177e2005-04-16 15:20:36 -070081#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */
82
83#define R8169_REGS_SIZE 256
84#define R8169_NAPI_WEIGHT 64
85#define NUM_TX_DESC 64 /* Number of Tx descriptor registers */
Timo Teräs9fba0812013-01-15 21:01:24 +000086#define NUM_RX_DESC 256U /* Number of Rx descriptor registers */
Linus Torvalds1da177e2005-04-16 15:20:36 -070087#define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc))
88#define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc))
89
90#define RTL8169_TX_TIMEOUT (6*HZ)
91#define RTL8169_PHY_TIMEOUT (10*HZ)
92
93/* write/read MMIO register */
94#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg))
95#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg))
96#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg))
97#define RTL_R8(reg) readb (ioaddr + (reg))
98#define RTL_R16(reg) readw (ioaddr + (reg))
Junchang Wang06f555f2010-05-30 02:26:07 +000099#define RTL_R32(reg) readl (ioaddr + (reg))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100
101enum mac_version {
Francois Romieu85bffe62011-04-27 08:22:39 +0200102 RTL_GIGA_MAC_VER_01 = 0,
103 RTL_GIGA_MAC_VER_02,
104 RTL_GIGA_MAC_VER_03,
105 RTL_GIGA_MAC_VER_04,
106 RTL_GIGA_MAC_VER_05,
107 RTL_GIGA_MAC_VER_06,
108 RTL_GIGA_MAC_VER_07,
109 RTL_GIGA_MAC_VER_08,
110 RTL_GIGA_MAC_VER_09,
111 RTL_GIGA_MAC_VER_10,
112 RTL_GIGA_MAC_VER_11,
113 RTL_GIGA_MAC_VER_12,
114 RTL_GIGA_MAC_VER_13,
115 RTL_GIGA_MAC_VER_14,
116 RTL_GIGA_MAC_VER_15,
117 RTL_GIGA_MAC_VER_16,
118 RTL_GIGA_MAC_VER_17,
119 RTL_GIGA_MAC_VER_18,
120 RTL_GIGA_MAC_VER_19,
121 RTL_GIGA_MAC_VER_20,
122 RTL_GIGA_MAC_VER_21,
123 RTL_GIGA_MAC_VER_22,
124 RTL_GIGA_MAC_VER_23,
125 RTL_GIGA_MAC_VER_24,
126 RTL_GIGA_MAC_VER_25,
127 RTL_GIGA_MAC_VER_26,
128 RTL_GIGA_MAC_VER_27,
129 RTL_GIGA_MAC_VER_28,
130 RTL_GIGA_MAC_VER_29,
131 RTL_GIGA_MAC_VER_30,
132 RTL_GIGA_MAC_VER_31,
133 RTL_GIGA_MAC_VER_32,
134 RTL_GIGA_MAC_VER_33,
Hayes Wang70090422011-07-06 15:58:06 +0800135 RTL_GIGA_MAC_VER_34,
Hayes Wangc2218922011-09-06 16:55:18 +0800136 RTL_GIGA_MAC_VER_35,
137 RTL_GIGA_MAC_VER_36,
Hayes Wang7e18dca2012-03-30 14:33:02 +0800138 RTL_GIGA_MAC_VER_37,
Hayes Wangb3d7b2f2012-03-30 14:48:06 +0800139 RTL_GIGA_MAC_VER_38,
Hayes Wang5598bfe2012-07-02 17:23:21 +0800140 RTL_GIGA_MAC_VER_39,
Hayes Wangc5583862012-07-02 17:23:22 +0800141 RTL_GIGA_MAC_VER_40,
142 RTL_GIGA_MAC_VER_41,
Francois Romieu85bffe62011-04-27 08:22:39 +0200143 RTL_GIGA_MAC_NONE = 0xff,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144};
145
Francois Romieu2b7b4312011-04-18 22:53:24 -0700146enum rtl_tx_desc_version {
147 RTL_TD_0 = 0,
148 RTL_TD_1 = 1,
149};
150
Francois Romieud58d46b2011-05-03 16:38:29 +0200151#define JUMBO_1K ETH_DATA_LEN
152#define JUMBO_4K (4*1024 - ETH_HLEN - 2)
153#define JUMBO_6K (6*1024 - ETH_HLEN - 2)
154#define JUMBO_7K (7*1024 - ETH_HLEN - 2)
155#define JUMBO_9K (9*1024 - ETH_HLEN - 2)
156
157#define _R(NAME,TD,FW,SZ,B) { \
158 .name = NAME, \
159 .txd_version = TD, \
160 .fw_name = FW, \
161 .jumbo_max = SZ, \
162 .jumbo_tx_csum = B \
163}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164
Jesper Juhl3c6bee12006-01-09 20:54:01 -0800165static const struct {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166 const char *name;
Francois Romieu2b7b4312011-04-18 22:53:24 -0700167 enum rtl_tx_desc_version txd_version;
Francois Romieu85bffe62011-04-27 08:22:39 +0200168 const char *fw_name;
Francois Romieud58d46b2011-05-03 16:38:29 +0200169 u16 jumbo_max;
170 bool jumbo_tx_csum;
Francois Romieu85bffe62011-04-27 08:22:39 +0200171} rtl_chip_infos[] = {
172 /* PCI devices. */
173 [RTL_GIGA_MAC_VER_01] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200174 _R("RTL8169", RTL_TD_0, NULL, JUMBO_7K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200175 [RTL_GIGA_MAC_VER_02] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200176 _R("RTL8169s", RTL_TD_0, NULL, JUMBO_7K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200177 [RTL_GIGA_MAC_VER_03] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200178 _R("RTL8110s", RTL_TD_0, NULL, JUMBO_7K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200179 [RTL_GIGA_MAC_VER_04] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200180 _R("RTL8169sb/8110sb", RTL_TD_0, NULL, JUMBO_7K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200181 [RTL_GIGA_MAC_VER_05] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200182 _R("RTL8169sc/8110sc", RTL_TD_0, NULL, JUMBO_7K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200183 [RTL_GIGA_MAC_VER_06] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200184 _R("RTL8169sc/8110sc", RTL_TD_0, NULL, JUMBO_7K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200185 /* PCI-E devices. */
186 [RTL_GIGA_MAC_VER_07] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200187 _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200188 [RTL_GIGA_MAC_VER_08] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200189 _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200190 [RTL_GIGA_MAC_VER_09] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200191 _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200192 [RTL_GIGA_MAC_VER_10] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200193 _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200194 [RTL_GIGA_MAC_VER_11] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200195 _R("RTL8168b/8111b", RTL_TD_0, NULL, JUMBO_4K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200196 [RTL_GIGA_MAC_VER_12] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200197 _R("RTL8168b/8111b", RTL_TD_0, NULL, JUMBO_4K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200198 [RTL_GIGA_MAC_VER_13] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200199 _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200200 [RTL_GIGA_MAC_VER_14] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200201 _R("RTL8100e", RTL_TD_0, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200202 [RTL_GIGA_MAC_VER_15] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200203 _R("RTL8100e", RTL_TD_0, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200204 [RTL_GIGA_MAC_VER_16] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200205 _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200206 [RTL_GIGA_MAC_VER_17] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200207 _R("RTL8168b/8111b", RTL_TD_1, NULL, JUMBO_4K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200208 [RTL_GIGA_MAC_VER_18] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200209 _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200210 [RTL_GIGA_MAC_VER_19] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200211 _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200212 [RTL_GIGA_MAC_VER_20] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200213 _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200214 [RTL_GIGA_MAC_VER_21] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200215 _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200216 [RTL_GIGA_MAC_VER_22] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200217 _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200218 [RTL_GIGA_MAC_VER_23] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200219 _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200220 [RTL_GIGA_MAC_VER_24] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200221 _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200222 [RTL_GIGA_MAC_VER_25] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200223 _R("RTL8168d/8111d", RTL_TD_1, FIRMWARE_8168D_1,
224 JUMBO_9K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200225 [RTL_GIGA_MAC_VER_26] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200226 _R("RTL8168d/8111d", RTL_TD_1, FIRMWARE_8168D_2,
227 JUMBO_9K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200228 [RTL_GIGA_MAC_VER_27] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200229 _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200230 [RTL_GIGA_MAC_VER_28] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200231 _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200232 [RTL_GIGA_MAC_VER_29] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200233 _R("RTL8105e", RTL_TD_1, FIRMWARE_8105E_1,
234 JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200235 [RTL_GIGA_MAC_VER_30] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200236 _R("RTL8105e", RTL_TD_1, FIRMWARE_8105E_1,
237 JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200238 [RTL_GIGA_MAC_VER_31] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200239 _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200240 [RTL_GIGA_MAC_VER_32] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200241 _R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_1,
242 JUMBO_9K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200243 [RTL_GIGA_MAC_VER_33] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200244 _R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_2,
245 JUMBO_9K, false),
Hayes Wang70090422011-07-06 15:58:06 +0800246 [RTL_GIGA_MAC_VER_34] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200247 _R("RTL8168evl/8111evl",RTL_TD_1, FIRMWARE_8168E_3,
248 JUMBO_9K, false),
Hayes Wangc2218922011-09-06 16:55:18 +0800249 [RTL_GIGA_MAC_VER_35] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200250 _R("RTL8168f/8111f", RTL_TD_1, FIRMWARE_8168F_1,
251 JUMBO_9K, false),
Hayes Wangc2218922011-09-06 16:55:18 +0800252 [RTL_GIGA_MAC_VER_36] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200253 _R("RTL8168f/8111f", RTL_TD_1, FIRMWARE_8168F_2,
254 JUMBO_9K, false),
Hayes Wang7e18dca2012-03-30 14:33:02 +0800255 [RTL_GIGA_MAC_VER_37] =
256 _R("RTL8402", RTL_TD_1, FIRMWARE_8402_1,
257 JUMBO_1K, true),
Hayes Wangb3d7b2f2012-03-30 14:48:06 +0800258 [RTL_GIGA_MAC_VER_38] =
259 _R("RTL8411", RTL_TD_1, FIRMWARE_8411_1,
260 JUMBO_9K, false),
Hayes Wang5598bfe2012-07-02 17:23:21 +0800261 [RTL_GIGA_MAC_VER_39] =
262 _R("RTL8106e", RTL_TD_1, FIRMWARE_8106E_1,
263 JUMBO_1K, true),
Hayes Wangc5583862012-07-02 17:23:22 +0800264 [RTL_GIGA_MAC_VER_40] =
265 _R("RTL8168g/8111g", RTL_TD_1, FIRMWARE_8168G_1,
266 JUMBO_9K, false),
267 [RTL_GIGA_MAC_VER_41] =
268 _R("RTL8168g/8111g", RTL_TD_1, NULL, JUMBO_9K, false),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269};
270#undef _R
271
Francois Romieubcf0bf92006-07-26 23:14:13 +0200272enum cfg_version {
273 RTL_CFG_0 = 0x00,
274 RTL_CFG_1,
275 RTL_CFG_2
276};
277
Alexey Dobriyana3aa1882010-01-07 11:58:11 +0000278static DEFINE_PCI_DEVICE_TABLE(rtl8169_pci_tbl) = {
Francois Romieubcf0bf92006-07-26 23:14:13 +0200279 { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 },
Francois Romieud2eed8c2006-08-31 22:01:07 +0200280 { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 },
Francois Romieud81bf552006-09-20 21:31:20 +0200281 { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 },
Francois Romieu07ce4062007-02-23 23:36:39 +0100282 { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 },
Francois Romieubcf0bf92006-07-26 23:14:13 +0200283 { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 },
Francois Romieu2a35cfa2012-08-31 23:06:17 +0200284 { PCI_VENDOR_ID_DLINK, 0x4300,
285 PCI_VENDOR_ID_DLINK, 0x4b10, 0, 0, RTL_CFG_1 },
Francois Romieubcf0bf92006-07-26 23:14:13 +0200286 { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 },
Lennart Sorensen93a3aa22011-07-28 13:18:11 +0000287 { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4302), 0, 0, RTL_CFG_0 },
Francois Romieubc1660b2007-10-12 23:58:09 +0200288 { PCI_DEVICE(PCI_VENDOR_ID_AT, 0xc107), 0, 0, RTL_CFG_0 },
Francois Romieubcf0bf92006-07-26 23:14:13 +0200289 { PCI_DEVICE(0x16ec, 0x0116), 0, 0, RTL_CFG_0 },
290 { PCI_VENDOR_ID_LINKSYS, 0x1032,
291 PCI_ANY_ID, 0x0024, 0, 0, RTL_CFG_0 },
Ciaran McCreesh11d2e282007-11-01 22:48:15 +0100292 { 0x0001, 0x8168,
293 PCI_ANY_ID, 0x2410, 0, 0, RTL_CFG_2 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294 {0,},
295};
296
297MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl);
298
Eric Dumazet6f0333b2010-10-11 11:17:47 +0000299static int rx_buf_sz = 16383;
David S. Miller4300e8c2010-03-26 10:23:30 -0700300static int use_dac;
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +0200301static struct {
302 u32 msg_enable;
303} debug = { -1 };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304
Francois Romieu07d3f512007-02-21 22:40:46 +0100305enum rtl_registers {
306 MAC0 = 0, /* Ethernet hardware address. */
Francois Romieu773d2022007-01-31 23:47:43 +0100307 MAC4 = 4,
Francois Romieu07d3f512007-02-21 22:40:46 +0100308 MAR0 = 8, /* Multicast filter. */
309 CounterAddrLow = 0x10,
310 CounterAddrHigh = 0x14,
311 TxDescStartAddrLow = 0x20,
312 TxDescStartAddrHigh = 0x24,
313 TxHDescStartAddrLow = 0x28,
314 TxHDescStartAddrHigh = 0x2c,
315 FLASH = 0x30,
316 ERSR = 0x36,
317 ChipCmd = 0x37,
318 TxPoll = 0x38,
319 IntrMask = 0x3c,
320 IntrStatus = 0x3e,
Francois Romieu2b7b4312011-04-18 22:53:24 -0700321
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800322 TxConfig = 0x40,
323#define TXCFG_AUTO_FIFO (1 << 7) /* 8111e-vl */
324#define TXCFG_EMPTY (1 << 11) /* 8111e-vl */
325
326 RxConfig = 0x44,
327#define RX128_INT_EN (1 << 15) /* 8111c and later */
328#define RX_MULTI_EN (1 << 14) /* 8111c only */
329#define RXCFG_FIFO_SHIFT 13
330 /* No threshold before first PCI xfer */
331#define RX_FIFO_THRESH (7 << RXCFG_FIFO_SHIFT)
332#define RXCFG_DMA_SHIFT 8
333 /* Unlimited maximum PCI burst. */
334#define RX_DMA_BURST (7 << RXCFG_DMA_SHIFT)
Francois Romieu2b7b4312011-04-18 22:53:24 -0700335
Francois Romieu07d3f512007-02-21 22:40:46 +0100336 RxMissed = 0x4c,
337 Cfg9346 = 0x50,
338 Config0 = 0x51,
339 Config1 = 0x52,
340 Config2 = 0x53,
Francois Romieud387b422012-04-17 11:12:01 +0200341#define PME_SIGNAL (1 << 5) /* 8168c and later */
342
Francois Romieu07d3f512007-02-21 22:40:46 +0100343 Config3 = 0x54,
344 Config4 = 0x55,
345 Config5 = 0x56,
346 MultiIntr = 0x5c,
347 PHYAR = 0x60,
Francois Romieu07d3f512007-02-21 22:40:46 +0100348 PHYstatus = 0x6c,
349 RxMaxSize = 0xda,
350 CPlusCmd = 0xe0,
351 IntrMitigate = 0xe2,
352 RxDescAddrLow = 0xe4,
353 RxDescAddrHigh = 0xe8,
françois romieuf0298f82011-01-03 15:07:42 +0000354 EarlyTxThres = 0xec, /* 8169. Unit of 32 bytes. */
355
356#define NoEarlyTx 0x3f /* Max value : no early transmit. */
357
358 MaxTxPacketSize = 0xec, /* 8101/8168. Unit of 128 bytes. */
359
360#define TxPacketMax (8064 >> 7)
Hayes Wang3090bd92011-09-06 16:55:15 +0800361#define EarlySize 0x27
françois romieuf0298f82011-01-03 15:07:42 +0000362
Francois Romieu07d3f512007-02-21 22:40:46 +0100363 FuncEvent = 0xf0,
364 FuncEventMask = 0xf4,
365 FuncPresetState = 0xf8,
366 FuncForceEvent = 0xfc,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367};
368
Francois Romieuf162a5d2008-06-01 22:37:49 +0200369enum rtl8110_registers {
370 TBICSR = 0x64,
371 TBI_ANAR = 0x68,
372 TBI_LPAR = 0x6a,
373};
374
375enum rtl8168_8101_registers {
376 CSIDR = 0x64,
377 CSIAR = 0x68,
378#define CSIAR_FLAG 0x80000000
379#define CSIAR_WRITE_CMD 0x80000000
380#define CSIAR_BYTE_ENABLE 0x0f
381#define CSIAR_BYTE_ENABLE_SHIFT 12
382#define CSIAR_ADDR_MASK 0x0fff
Hayes Wang7e18dca2012-03-30 14:33:02 +0800383#define CSIAR_FUNC_CARD 0x00000000
384#define CSIAR_FUNC_SDIO 0x00010000
385#define CSIAR_FUNC_NIC 0x00020000
françois romieu065c27c2011-01-03 15:08:12 +0000386 PMCH = 0x6f,
Francois Romieuf162a5d2008-06-01 22:37:49 +0200387 EPHYAR = 0x80,
388#define EPHYAR_FLAG 0x80000000
389#define EPHYAR_WRITE_CMD 0x80000000
390#define EPHYAR_REG_MASK 0x1f
391#define EPHYAR_REG_SHIFT 16
392#define EPHYAR_DATA_MASK 0xffff
Hayes Wang5a5e4442011-02-22 17:26:21 +0800393 DLLPR = 0xd0,
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800394#define PFM_EN (1 << 6)
Francois Romieuf162a5d2008-06-01 22:37:49 +0200395 DBG_REG = 0xd1,
396#define FIX_NAK_1 (1 << 4)
397#define FIX_NAK_2 (1 << 3)
Hayes Wang5a5e4442011-02-22 17:26:21 +0800398 TWSI = 0xd2,
399 MCU = 0xd3,
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800400#define NOW_IS_OOB (1 << 7)
Hayes Wangc5583862012-07-02 17:23:22 +0800401#define TX_EMPTY (1 << 5)
402#define RX_EMPTY (1 << 4)
403#define RXTX_EMPTY (TX_EMPTY | RX_EMPTY)
Hayes Wang5a5e4442011-02-22 17:26:21 +0800404#define EN_NDP (1 << 3)
405#define EN_OOB_RESET (1 << 2)
Hayes Wangc5583862012-07-02 17:23:22 +0800406#define LINK_LIST_RDY (1 << 1)
françois romieudaf9df62009-10-07 12:44:20 +0000407 EFUSEAR = 0xdc,
408#define EFUSEAR_FLAG 0x80000000
409#define EFUSEAR_WRITE_CMD 0x80000000
410#define EFUSEAR_READ_CMD 0x00000000
411#define EFUSEAR_REG_MASK 0x03ff
412#define EFUSEAR_REG_SHIFT 8
413#define EFUSEAR_DATA_MASK 0xff
Francois Romieuf162a5d2008-06-01 22:37:49 +0200414};
415
françois romieuc0e45c12011-01-03 15:08:04 +0000416enum rtl8168_registers {
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800417 LED_FREQ = 0x1a,
418 EEE_LED = 0x1b,
françois romieub646d902011-01-03 15:08:21 +0000419 ERIDR = 0x70,
420 ERIAR = 0x74,
421#define ERIAR_FLAG 0x80000000
422#define ERIAR_WRITE_CMD 0x80000000
423#define ERIAR_READ_CMD 0x00000000
424#define ERIAR_ADDR_BYTE_ALIGN 4
françois romieub646d902011-01-03 15:08:21 +0000425#define ERIAR_TYPE_SHIFT 16
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800426#define ERIAR_EXGMAC (0x00 << ERIAR_TYPE_SHIFT)
427#define ERIAR_MSIX (0x01 << ERIAR_TYPE_SHIFT)
428#define ERIAR_ASF (0x02 << ERIAR_TYPE_SHIFT)
429#define ERIAR_MASK_SHIFT 12
430#define ERIAR_MASK_0001 (0x1 << ERIAR_MASK_SHIFT)
431#define ERIAR_MASK_0011 (0x3 << ERIAR_MASK_SHIFT)
Hayes Wangc5583862012-07-02 17:23:22 +0800432#define ERIAR_MASK_0101 (0x5 << ERIAR_MASK_SHIFT)
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800433#define ERIAR_MASK_1111 (0xf << ERIAR_MASK_SHIFT)
françois romieuc0e45c12011-01-03 15:08:04 +0000434 EPHY_RXER_NUM = 0x7c,
435 OCPDR = 0xb0, /* OCP GPHY access */
436#define OCPDR_WRITE_CMD 0x80000000
437#define OCPDR_READ_CMD 0x00000000
438#define OCPDR_REG_MASK 0x7f
439#define OCPDR_GPHY_REG_SHIFT 16
440#define OCPDR_DATA_MASK 0xffff
441 OCPAR = 0xb4,
442#define OCPAR_FLAG 0x80000000
443#define OCPAR_GPHY_WRITE_CMD 0x8000f060
444#define OCPAR_GPHY_READ_CMD 0x0000f060
Hayes Wangc5583862012-07-02 17:23:22 +0800445 GPHY_OCP = 0xb8,
hayeswang01dc7fe2011-03-21 01:50:28 +0000446 RDSAR1 = 0xd0, /* 8168c only. Undocumented on 8168dp */
447 MISC = 0xf0, /* 8168e only. */
Francois Romieucecb5fd2011-04-01 10:21:07 +0200448#define TXPLA_RST (1 << 29)
Hayes Wang5598bfe2012-07-02 17:23:21 +0800449#define DISABLE_LAN_EN (1 << 23) /* Enable GPIO pin */
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800450#define PWM_EN (1 << 22)
Hayes Wangc5583862012-07-02 17:23:22 +0800451#define RXDV_GATED_EN (1 << 19)
Hayes Wang5598bfe2012-07-02 17:23:21 +0800452#define EARLY_TALLY_EN (1 << 16)
françois romieuc0e45c12011-01-03 15:08:04 +0000453};
454
Francois Romieu07d3f512007-02-21 22:40:46 +0100455enum rtl_register_content {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456 /* InterruptStatusBits */
Francois Romieu07d3f512007-02-21 22:40:46 +0100457 SYSErr = 0x8000,
458 PCSTimeout = 0x4000,
459 SWInt = 0x0100,
460 TxDescUnavail = 0x0080,
461 RxFIFOOver = 0x0040,
462 LinkChg = 0x0020,
463 RxOverflow = 0x0010,
464 TxErr = 0x0008,
465 TxOK = 0x0004,
466 RxErr = 0x0002,
467 RxOK = 0x0001,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468
469 /* RxStatusDesc */
David S. Miller8decf862011-09-22 03:23:13 -0400470 RxBOVF = (1 << 24),
Francois Romieu9dccf612006-05-14 12:31:17 +0200471 RxFOVF = (1 << 23),
472 RxRWT = (1 << 22),
473 RxRES = (1 << 21),
474 RxRUNT = (1 << 20),
475 RxCRC = (1 << 19),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476
477 /* ChipCmdBits */
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800478 StopReq = 0x80,
Francois Romieu07d3f512007-02-21 22:40:46 +0100479 CmdReset = 0x10,
480 CmdRxEnb = 0x08,
481 CmdTxEnb = 0x04,
482 RxBufEmpty = 0x01,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483
Francois Romieu275391a2007-02-23 23:50:28 +0100484 /* TXPoll register p.5 */
485 HPQ = 0x80, /* Poll cmd on the high prio queue */
486 NPQ = 0x40, /* Poll cmd on the low prio queue */
487 FSWInt = 0x01, /* Forced software interrupt */
488
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489 /* Cfg9346Bits */
Francois Romieu07d3f512007-02-21 22:40:46 +0100490 Cfg9346_Lock = 0x00,
491 Cfg9346_Unlock = 0xc0,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492
493 /* rx_mode_bits */
Francois Romieu07d3f512007-02-21 22:40:46 +0100494 AcceptErr = 0x20,
495 AcceptRunt = 0x10,
496 AcceptBroadcast = 0x08,
497 AcceptMulticast = 0x04,
498 AcceptMyPhys = 0x02,
499 AcceptAllPhys = 0x01,
Francois Romieu1687b562011-07-19 17:21:29 +0200500#define RX_CONFIG_ACCEPT_MASK 0x3f
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502 /* TxConfigBits */
503 TxInterFrameGapShift = 24,
504 TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */
505
Francois Romieu5d06a992006-02-23 00:47:58 +0100506 /* Config1 register p.24 */
Francois Romieuf162a5d2008-06-01 22:37:49 +0200507 LEDS1 = (1 << 7),
508 LEDS0 = (1 << 6),
Francois Romieuf162a5d2008-06-01 22:37:49 +0200509 Speed_down = (1 << 4),
510 MEMMAP = (1 << 3),
511 IOMAP = (1 << 2),
512 VPD = (1 << 1),
Francois Romieu5d06a992006-02-23 00:47:58 +0100513 PMEnable = (1 << 0), /* Power Management Enable */
514
Francois Romieu6dccd162007-02-13 23:38:05 +0100515 /* Config2 register p. 25 */
françois romieu2ca6cf02011-12-15 08:37:43 +0000516 MSIEnable = (1 << 5), /* 8169 only. Reserved in the 8168. */
Francois Romieu6dccd162007-02-13 23:38:05 +0100517 PCI_Clock_66MHz = 0x01,
518 PCI_Clock_33MHz = 0x00,
519
Francois Romieu61a4dcc2006-02-23 00:55:25 +0100520 /* Config3 register p.25 */
521 MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */
522 LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */
Francois Romieud58d46b2011-05-03 16:38:29 +0200523 Jumbo_En0 = (1 << 2), /* 8168 only. Reserved in the 8168b */
Francois Romieuf162a5d2008-06-01 22:37:49 +0200524 Beacon_en = (1 << 0), /* 8168 only. Reserved in the 8168b */
Francois Romieu61a4dcc2006-02-23 00:55:25 +0100525
Francois Romieud58d46b2011-05-03 16:38:29 +0200526 /* Config4 register */
527 Jumbo_En1 = (1 << 1), /* 8168 only. Reserved in the 8168b */
528
Francois Romieu5d06a992006-02-23 00:47:58 +0100529 /* Config5 register p.27 */
Francois Romieu61a4dcc2006-02-23 00:55:25 +0100530 BWF = (1 << 6), /* Accept Broadcast wakeup frame */
531 MWF = (1 << 5), /* Accept Multicast wakeup frame */
532 UWF = (1 << 4), /* Accept Unicast wakeup frame */
Francois Romieucecb5fd2011-04-01 10:21:07 +0200533 Spi_en = (1 << 3),
Francois Romieu61a4dcc2006-02-23 00:55:25 +0100534 LanWake = (1 << 1), /* LanWake enable/disable */
Francois Romieu5d06a992006-02-23 00:47:58 +0100535 PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */
536
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537 /* TBICSR p.28 */
538 TBIReset = 0x80000000,
539 TBILoopback = 0x40000000,
540 TBINwEnable = 0x20000000,
541 TBINwRestart = 0x10000000,
542 TBILinkOk = 0x02000000,
543 TBINwComplete = 0x01000000,
544
545 /* CPlusCmd p.31 */
Francois Romieuf162a5d2008-06-01 22:37:49 +0200546 EnableBist = (1 << 15), // 8168 8101
547 Mac_dbgo_oe = (1 << 14), // 8168 8101
548 Normal_mode = (1 << 13), // unused
549 Force_half_dup = (1 << 12), // 8168 8101
550 Force_rxflow_en = (1 << 11), // 8168 8101
551 Force_txflow_en = (1 << 10), // 8168 8101
552 Cxpl_dbg_sel = (1 << 9), // 8168 8101
553 ASF = (1 << 8), // 8168 8101
554 PktCntrDisable = (1 << 7), // 8168 8101
555 Mac_dbgo_sel = 0x001c, // 8168
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556 RxVlan = (1 << 6),
557 RxChkSum = (1 << 5),
558 PCIDAC = (1 << 4),
559 PCIMulRW = (1 << 3),
Francois Romieu0e485152007-02-20 00:00:26 +0100560 INTT_0 = 0x0000, // 8168
561 INTT_1 = 0x0001, // 8168
562 INTT_2 = 0x0002, // 8168
563 INTT_3 = 0x0003, // 8168
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564
565 /* rtl8169_PHYstatus */
Francois Romieu07d3f512007-02-21 22:40:46 +0100566 TBI_Enable = 0x80,
567 TxFlowCtrl = 0x40,
568 RxFlowCtrl = 0x20,
569 _1000bpsF = 0x10,
570 _100bps = 0x08,
571 _10bps = 0x04,
572 LinkStatus = 0x02,
573 FullDup = 0x01,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575 /* _TBICSRBit */
Francois Romieu07d3f512007-02-21 22:40:46 +0100576 TBILinkOK = 0x02000000,
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +0200577
578 /* DumpCounterCommand */
Francois Romieu07d3f512007-02-21 22:40:46 +0100579 CounterDump = 0x8,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580};
581
Francois Romieu2b7b4312011-04-18 22:53:24 -0700582enum rtl_desc_bit {
583 /* First doubleword. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584 DescOwn = (1 << 31), /* Descriptor is owned by NIC */
585 RingEnd = (1 << 30), /* End of descriptor ring */
586 FirstFrag = (1 << 29), /* First segment of a packet */
587 LastFrag = (1 << 28), /* Final segment of a packet */
Francois Romieu2b7b4312011-04-18 22:53:24 -0700588};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589
Francois Romieu2b7b4312011-04-18 22:53:24 -0700590/* Generic case. */
591enum rtl_tx_desc_bit {
592 /* First doubleword. */
593 TD_LSO = (1 << 27), /* Large Send Offload */
594#define TD_MSS_MAX 0x07ffu /* MSS value */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595
Francois Romieu2b7b4312011-04-18 22:53:24 -0700596 /* Second doubleword. */
597 TxVlanTag = (1 << 17), /* Add VLAN tag */
598};
599
600/* 8169, 8168b and 810x except 8102e. */
601enum rtl_tx_desc_bit_0 {
602 /* First doubleword. */
603#define TD0_MSS_SHIFT 16 /* MSS position (11 bits) */
604 TD0_TCP_CS = (1 << 16), /* Calculate TCP/IP checksum */
605 TD0_UDP_CS = (1 << 17), /* Calculate UDP/IP checksum */
606 TD0_IP_CS = (1 << 18), /* Calculate IP checksum */
607};
608
609/* 8102e, 8168c and beyond. */
610enum rtl_tx_desc_bit_1 {
611 /* Second doubleword. */
612#define TD1_MSS_SHIFT 18 /* MSS position (11 bits) */
613 TD1_IP_CS = (1 << 29), /* Calculate IP checksum */
614 TD1_TCP_CS = (1 << 30), /* Calculate TCP/IP checksum */
615 TD1_UDP_CS = (1 << 31), /* Calculate UDP/IP checksum */
616};
617
618static const struct rtl_tx_desc_info {
619 struct {
620 u32 udp;
621 u32 tcp;
622 } checksum;
623 u16 mss_shift;
624 u16 opts_offset;
625} tx_desc_info [] = {
626 [RTL_TD_0] = {
627 .checksum = {
628 .udp = TD0_IP_CS | TD0_UDP_CS,
629 .tcp = TD0_IP_CS | TD0_TCP_CS
630 },
631 .mss_shift = TD0_MSS_SHIFT,
632 .opts_offset = 0
633 },
634 [RTL_TD_1] = {
635 .checksum = {
636 .udp = TD1_IP_CS | TD1_UDP_CS,
637 .tcp = TD1_IP_CS | TD1_TCP_CS
638 },
639 .mss_shift = TD1_MSS_SHIFT,
640 .opts_offset = 1
641 }
642};
643
644enum rtl_rx_desc_bit {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645 /* Rx private */
646 PID1 = (1 << 18), /* Protocol ID bit 1/2 */
647 PID0 = (1 << 17), /* Protocol ID bit 2/2 */
648
649#define RxProtoUDP (PID1)
650#define RxProtoTCP (PID0)
651#define RxProtoIP (PID1 | PID0)
652#define RxProtoMask RxProtoIP
653
654 IPFail = (1 << 16), /* IP checksum failed */
655 UDPFail = (1 << 15), /* UDP/IP checksum failed */
656 TCPFail = (1 << 14), /* TCP/IP checksum failed */
657 RxVlanTag = (1 << 16), /* VLAN tag available */
658};
659
660#define RsvdMask 0x3fffc000
661
662struct TxDesc {
Rolf Eike Beer6cccd6e2007-05-21 22:11:04 +0200663 __le32 opts1;
664 __le32 opts2;
665 __le64 addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666};
667
668struct RxDesc {
Rolf Eike Beer6cccd6e2007-05-21 22:11:04 +0200669 __le32 opts1;
670 __le32 opts2;
671 __le64 addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672};
673
674struct ring_info {
675 struct sk_buff *skb;
676 u32 len;
677 u8 __pad[sizeof(void *) - sizeof(u32)];
678};
679
Francois Romieuf23e7fd2007-10-04 22:36:14 +0200680enum features {
Francois Romieuccdffb92008-07-26 14:26:06 +0200681 RTL_FEATURE_WOL = (1 << 0),
682 RTL_FEATURE_MSI = (1 << 1),
683 RTL_FEATURE_GMII = (1 << 2),
Francois Romieuf23e7fd2007-10-04 22:36:14 +0200684};
685
Ivan Vecera355423d2009-02-06 21:49:57 -0800686struct rtl8169_counters {
687 __le64 tx_packets;
688 __le64 rx_packets;
689 __le64 tx_errors;
690 __le32 rx_errors;
691 __le16 rx_missed;
692 __le16 align_errors;
693 __le32 tx_one_collision;
694 __le32 tx_multi_collision;
695 __le64 rx_unicast;
696 __le64 rx_broadcast;
697 __le32 rx_multicast;
698 __le16 tx_aborted;
699 __le16 tx_underun;
700};
701
Francois Romieuda78dbf2012-01-26 14:18:23 +0100702enum rtl_flag {
Francois Romieu6c4a70c2012-01-31 10:56:44 +0100703 RTL_FLAG_TASK_ENABLED,
Francois Romieuda78dbf2012-01-26 14:18:23 +0100704 RTL_FLAG_TASK_SLOW_PENDING,
705 RTL_FLAG_TASK_RESET_PENDING,
706 RTL_FLAG_TASK_PHY_PENDING,
707 RTL_FLAG_MAX
708};
709
Junchang Wang8027aa22012-03-04 23:30:32 +0100710struct rtl8169_stats {
711 u64 packets;
712 u64 bytes;
713 struct u64_stats_sync syncp;
714};
715
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716struct rtl8169_private {
717 void __iomem *mmio_addr; /* memory map physical address */
Francois Romieucecb5fd2011-04-01 10:21:07 +0200718 struct pci_dev *pci_dev;
David Howellsc4028952006-11-22 14:57:56 +0000719 struct net_device *dev;
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700720 struct napi_struct napi;
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +0200721 u32 msg_enable;
Francois Romieu2b7b4312011-04-18 22:53:24 -0700722 u16 txd_version;
723 u16 mac_version;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724 u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */
725 u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726 u32 dirty_tx;
Junchang Wang8027aa22012-03-04 23:30:32 +0100727 struct rtl8169_stats rx_stats;
728 struct rtl8169_stats tx_stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729 struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */
730 struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */
731 dma_addr_t TxPhyAddr;
732 dma_addr_t RxPhyAddr;
Eric Dumazet6f0333b2010-10-11 11:17:47 +0000733 void *Rx_databuff[NUM_RX_DESC]; /* Rx data buffers */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734 struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735 struct timer_list timer;
736 u16 cp_cmd;
Francois Romieuda78dbf2012-01-26 14:18:23 +0100737
738 u16 event_slow;
françois romieuc0e45c12011-01-03 15:08:04 +0000739
740 struct mdio_ops {
Francois Romieu24192212012-07-06 20:19:42 +0200741 void (*write)(struct rtl8169_private *, int, int);
742 int (*read)(struct rtl8169_private *, int);
françois romieuc0e45c12011-01-03 15:08:04 +0000743 } mdio_ops;
744
françois romieu065c27c2011-01-03 15:08:12 +0000745 struct pll_power_ops {
746 void (*down)(struct rtl8169_private *);
747 void (*up)(struct rtl8169_private *);
748 } pll_power_ops;
749
Francois Romieud58d46b2011-05-03 16:38:29 +0200750 struct jumbo_ops {
751 void (*enable)(struct rtl8169_private *);
752 void (*disable)(struct rtl8169_private *);
753 } jumbo_ops;
754
Hayes Wangbeb1fe12012-03-30 14:33:01 +0800755 struct csi_ops {
Francois Romieu52989f02012-07-06 13:37:00 +0200756 void (*write)(struct rtl8169_private *, int, int);
757 u32 (*read)(struct rtl8169_private *, int);
Hayes Wangbeb1fe12012-03-30 14:33:01 +0800758 } csi_ops;
759
Oliver Neukum54405cd2011-01-06 21:55:13 +0100760 int (*set_speed)(struct net_device *, u8 aneg, u16 sp, u8 dpx, u32 adv);
Francois Romieuccdffb92008-07-26 14:26:06 +0200761 int (*get_settings)(struct net_device *, struct ethtool_cmd *);
françois romieu4da19632011-01-03 15:07:55 +0000762 void (*phy_reset_enable)(struct rtl8169_private *tp);
Francois Romieu07ce4062007-02-23 23:36:39 +0100763 void (*hw_start)(struct net_device *);
françois romieu4da19632011-01-03 15:07:55 +0000764 unsigned int (*phy_reset_pending)(struct rtl8169_private *tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765 unsigned int (*link_ok)(void __iomem *);
Francois Romieu8b4ab282008-11-19 22:05:25 -0800766 int (*do_ioctl)(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd);
Francois Romieu4422bcd2012-01-26 11:23:32 +0100767
768 struct {
Francois Romieuda78dbf2012-01-26 14:18:23 +0100769 DECLARE_BITMAP(flags, RTL_FLAG_MAX);
770 struct mutex mutex;
Francois Romieu4422bcd2012-01-26 11:23:32 +0100771 struct work_struct work;
772 } wk;
773
Francois Romieuf23e7fd2007-10-04 22:36:14 +0200774 unsigned features;
Francois Romieuccdffb92008-07-26 14:26:06 +0200775
776 struct mii_if_info mii;
Ivan Vecera355423d2009-02-06 21:49:57 -0800777 struct rtl8169_counters counters;
Rafael J. Wysockie1759442010-03-14 14:33:51 +0000778 u32 saved_wolopts;
David S. Miller8decf862011-09-22 03:23:13 -0400779 u32 opts1_mask;
françois romieuf1e02ed2011-01-13 13:07:53 +0000780
Francois Romieub6ffd972011-06-17 17:00:05 +0200781 struct rtl_fw {
782 const struct firmware *fw;
Francois Romieu1c361ef2011-06-17 17:16:24 +0200783
784#define RTL_VER_SIZE 32
785
786 char version[RTL_VER_SIZE];
787
788 struct rtl_fw_phy_action {
789 __le32 *code;
790 size_t size;
791 } phy_action;
Francois Romieub6ffd972011-06-17 17:00:05 +0200792 } *rtl_fw;
Phil Carmody497888c2011-07-14 15:07:13 +0300793#define RTL_FIRMWARE_UNKNOWN ERR_PTR(-EAGAIN)
Hayes Wangc5583862012-07-02 17:23:22 +0800794
795 u32 ocp_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796};
797
Ralf Baechle979b6c12005-06-13 14:30:40 -0700798MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800module_param(use_dac, int, 0);
David S. Miller4300e8c2010-03-26 10:23:30 -0700801MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot.");
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +0200802module_param_named(debug, debug.msg_enable, int, 0);
803MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804MODULE_LICENSE("GPL");
805MODULE_VERSION(RTL8169_VERSION);
françois romieubca03d52011-01-03 15:07:31 +0000806MODULE_FIRMWARE(FIRMWARE_8168D_1);
807MODULE_FIRMWARE(FIRMWARE_8168D_2);
hayeswang01dc7fe2011-03-21 01:50:28 +0000808MODULE_FIRMWARE(FIRMWARE_8168E_1);
809MODULE_FIRMWARE(FIRMWARE_8168E_2);
David S. Miller8decf862011-09-22 03:23:13 -0400810MODULE_FIRMWARE(FIRMWARE_8168E_3);
Hayes Wang5a5e4442011-02-22 17:26:21 +0800811MODULE_FIRMWARE(FIRMWARE_8105E_1);
Hayes Wangc2218922011-09-06 16:55:18 +0800812MODULE_FIRMWARE(FIRMWARE_8168F_1);
813MODULE_FIRMWARE(FIRMWARE_8168F_2);
Hayes Wang7e18dca2012-03-30 14:33:02 +0800814MODULE_FIRMWARE(FIRMWARE_8402_1);
Hayes Wangb3d7b2f2012-03-30 14:48:06 +0800815MODULE_FIRMWARE(FIRMWARE_8411_1);
Hayes Wang5598bfe2012-07-02 17:23:21 +0800816MODULE_FIRMWARE(FIRMWARE_8106E_1);
Hayes Wangc5583862012-07-02 17:23:22 +0800817MODULE_FIRMWARE(FIRMWARE_8168G_1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818
Francois Romieuda78dbf2012-01-26 14:18:23 +0100819static void rtl_lock_work(struct rtl8169_private *tp)
820{
821 mutex_lock(&tp->wk.mutex);
822}
823
824static void rtl_unlock_work(struct rtl8169_private *tp)
825{
826 mutex_unlock(&tp->wk.mutex);
827}
828
Francois Romieud58d46b2011-05-03 16:38:29 +0200829static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force)
830{
Jiang Liu7d7903b2012-07-24 17:20:16 +0800831 pcie_capability_clear_and_set_word(pdev, PCI_EXP_DEVCTL,
832 PCI_EXP_DEVCTL_READRQ, force);
Francois Romieud58d46b2011-05-03 16:38:29 +0200833}
834
Francois Romieuffc46952012-07-06 14:19:23 +0200835struct rtl_cond {
836 bool (*check)(struct rtl8169_private *);
837 const char *msg;
838};
839
840static void rtl_udelay(unsigned int d)
841{
842 udelay(d);
843}
844
845static bool rtl_loop_wait(struct rtl8169_private *tp, const struct rtl_cond *c,
846 void (*delay)(unsigned int), unsigned int d, int n,
847 bool high)
848{
849 int i;
850
851 for (i = 0; i < n; i++) {
852 delay(d);
853 if (c->check(tp) == high)
854 return true;
855 }
Francois Romieu82e316e2012-07-11 23:39:51 +0200856 netif_err(tp, drv, tp->dev, "%s == %d (loop: %d, delay: %d).\n",
857 c->msg, !high, n, d);
Francois Romieuffc46952012-07-06 14:19:23 +0200858 return false;
859}
860
861static bool rtl_udelay_loop_wait_high(struct rtl8169_private *tp,
862 const struct rtl_cond *c,
863 unsigned int d, int n)
864{
865 return rtl_loop_wait(tp, c, rtl_udelay, d, n, true);
866}
867
868static bool rtl_udelay_loop_wait_low(struct rtl8169_private *tp,
869 const struct rtl_cond *c,
870 unsigned int d, int n)
871{
872 return rtl_loop_wait(tp, c, rtl_udelay, d, n, false);
873}
874
875static bool rtl_msleep_loop_wait_high(struct rtl8169_private *tp,
876 const struct rtl_cond *c,
877 unsigned int d, int n)
878{
879 return rtl_loop_wait(tp, c, msleep, d, n, true);
880}
881
882static bool rtl_msleep_loop_wait_low(struct rtl8169_private *tp,
883 const struct rtl_cond *c,
884 unsigned int d, int n)
885{
886 return rtl_loop_wait(tp, c, msleep, d, n, false);
887}
888
889#define DECLARE_RTL_COND(name) \
890static bool name ## _check(struct rtl8169_private *); \
891 \
892static const struct rtl_cond name = { \
893 .check = name ## _check, \
894 .msg = #name \
895}; \
896 \
897static bool name ## _check(struct rtl8169_private *tp)
898
899DECLARE_RTL_COND(rtl_ocpar_cond)
900{
901 void __iomem *ioaddr = tp->mmio_addr;
902
903 return RTL_R32(OCPAR) & OCPAR_FLAG;
904}
905
françois romieub646d902011-01-03 15:08:21 +0000906static u32 ocp_read(struct rtl8169_private *tp, u8 mask, u16 reg)
907{
908 void __iomem *ioaddr = tp->mmio_addr;
françois romieub646d902011-01-03 15:08:21 +0000909
910 RTL_W32(OCPAR, ((u32)mask & 0x0f) << 12 | (reg & 0x0fff));
Francois Romieuffc46952012-07-06 14:19:23 +0200911
912 return rtl_udelay_loop_wait_high(tp, &rtl_ocpar_cond, 100, 20) ?
913 RTL_R32(OCPDR) : ~0;
françois romieub646d902011-01-03 15:08:21 +0000914}
915
916static void ocp_write(struct rtl8169_private *tp, u8 mask, u16 reg, u32 data)
917{
918 void __iomem *ioaddr = tp->mmio_addr;
françois romieub646d902011-01-03 15:08:21 +0000919
920 RTL_W32(OCPDR, data);
921 RTL_W32(OCPAR, OCPAR_FLAG | ((u32)mask & 0x0f) << 12 | (reg & 0x0fff));
Francois Romieuffc46952012-07-06 14:19:23 +0200922
923 rtl_udelay_loop_wait_low(tp, &rtl_ocpar_cond, 100, 20);
924}
925
926DECLARE_RTL_COND(rtl_eriar_cond)
927{
928 void __iomem *ioaddr = tp->mmio_addr;
929
930 return RTL_R32(ERIAR) & ERIAR_FLAG;
françois romieub646d902011-01-03 15:08:21 +0000931}
932
Hayes Wangfac5b3c2011-02-22 17:26:20 +0800933static void rtl8168_oob_notify(struct rtl8169_private *tp, u8 cmd)
françois romieub646d902011-01-03 15:08:21 +0000934{
Hayes Wangfac5b3c2011-02-22 17:26:20 +0800935 void __iomem *ioaddr = tp->mmio_addr;
françois romieub646d902011-01-03 15:08:21 +0000936
937 RTL_W8(ERIDR, cmd);
938 RTL_W32(ERIAR, 0x800010e8);
939 msleep(2);
Francois Romieuffc46952012-07-06 14:19:23 +0200940
941 if (!rtl_udelay_loop_wait_low(tp, &rtl_eriar_cond, 100, 5))
942 return;
françois romieub646d902011-01-03 15:08:21 +0000943
Hayes Wangfac5b3c2011-02-22 17:26:20 +0800944 ocp_write(tp, 0x1, 0x30, 0x00000001);
françois romieub646d902011-01-03 15:08:21 +0000945}
946
947#define OOB_CMD_RESET 0x00
948#define OOB_CMD_DRIVER_START 0x05
949#define OOB_CMD_DRIVER_STOP 0x06
950
Francois Romieucecb5fd2011-04-01 10:21:07 +0200951static u16 rtl8168_get_ocp_reg(struct rtl8169_private *tp)
952{
953 return (tp->mac_version == RTL_GIGA_MAC_VER_31) ? 0xb8 : 0x10;
954}
955
Francois Romieuffc46952012-07-06 14:19:23 +0200956DECLARE_RTL_COND(rtl_ocp_read_cond)
françois romieub646d902011-01-03 15:08:21 +0000957{
Francois Romieucecb5fd2011-04-01 10:21:07 +0200958 u16 reg;
françois romieub646d902011-01-03 15:08:21 +0000959
Francois Romieucecb5fd2011-04-01 10:21:07 +0200960 reg = rtl8168_get_ocp_reg(tp);
hayeswang4804b3b2011-03-21 01:50:29 +0000961
Francois Romieuffc46952012-07-06 14:19:23 +0200962 return ocp_read(tp, 0x0f, reg) & 0x00000800;
963}
964
965static void rtl8168_driver_start(struct rtl8169_private *tp)
966{
967 rtl8168_oob_notify(tp, OOB_CMD_DRIVER_START);
968
969 rtl_msleep_loop_wait_high(tp, &rtl_ocp_read_cond, 10, 10);
françois romieub646d902011-01-03 15:08:21 +0000970}
971
972static void rtl8168_driver_stop(struct rtl8169_private *tp)
973{
françois romieub646d902011-01-03 15:08:21 +0000974 rtl8168_oob_notify(tp, OOB_CMD_DRIVER_STOP);
975
Francois Romieuffc46952012-07-06 14:19:23 +0200976 rtl_msleep_loop_wait_low(tp, &rtl_ocp_read_cond, 10, 10);
françois romieub646d902011-01-03 15:08:21 +0000977}
978
hayeswang4804b3b2011-03-21 01:50:29 +0000979static int r8168dp_check_dash(struct rtl8169_private *tp)
980{
Francois Romieucecb5fd2011-04-01 10:21:07 +0200981 u16 reg = rtl8168_get_ocp_reg(tp);
hayeswang4804b3b2011-03-21 01:50:29 +0000982
Francois Romieucecb5fd2011-04-01 10:21:07 +0200983 return (ocp_read(tp, 0x0f, reg) & 0x00008000) ? 1 : 0;
hayeswang4804b3b2011-03-21 01:50:29 +0000984}
françois romieub646d902011-01-03 15:08:21 +0000985
Hayes Wangc5583862012-07-02 17:23:22 +0800986static bool rtl_ocp_reg_failure(struct rtl8169_private *tp, u32 reg)
987{
988 if (reg & 0xffff0001) {
989 netif_err(tp, drv, tp->dev, "Invalid ocp reg %x!\n", reg);
990 return true;
991 }
992 return false;
993}
994
995DECLARE_RTL_COND(rtl_ocp_gphy_cond)
996{
997 void __iomem *ioaddr = tp->mmio_addr;
998
999 return RTL_R32(GPHY_OCP) & OCPAR_FLAG;
1000}
1001
1002static void r8168_phy_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)
1003{
1004 void __iomem *ioaddr = tp->mmio_addr;
1005
1006 if (rtl_ocp_reg_failure(tp, reg))
1007 return;
1008
1009 RTL_W32(GPHY_OCP, OCPAR_FLAG | (reg << 15) | data);
1010
1011 rtl_udelay_loop_wait_low(tp, &rtl_ocp_gphy_cond, 25, 10);
1012}
1013
1014static u16 r8168_phy_ocp_read(struct rtl8169_private *tp, u32 reg)
1015{
1016 void __iomem *ioaddr = tp->mmio_addr;
1017
1018 if (rtl_ocp_reg_failure(tp, reg))
1019 return 0;
1020
1021 RTL_W32(GPHY_OCP, reg << 15);
1022
1023 return rtl_udelay_loop_wait_high(tp, &rtl_ocp_gphy_cond, 25, 10) ?
1024 (RTL_R32(GPHY_OCP) & 0xffff) : ~0;
1025}
1026
1027static void rtl_w1w0_phy_ocp(struct rtl8169_private *tp, int reg, int p, int m)
1028{
1029 int val;
1030
1031 val = r8168_phy_ocp_read(tp, reg);
1032 r8168_phy_ocp_write(tp, reg, (val | p) & ~m);
1033}
1034
Hayes Wangc5583862012-07-02 17:23:22 +08001035static void r8168_mac_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)
1036{
1037 void __iomem *ioaddr = tp->mmio_addr;
1038
1039 if (rtl_ocp_reg_failure(tp, reg))
1040 return;
1041
1042 RTL_W32(OCPDR, OCPAR_FLAG | (reg << 15) | data);
Hayes Wangc5583862012-07-02 17:23:22 +08001043}
1044
1045static u16 r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg)
1046{
1047 void __iomem *ioaddr = tp->mmio_addr;
1048
1049 if (rtl_ocp_reg_failure(tp, reg))
1050 return 0;
1051
1052 RTL_W32(OCPDR, reg << 15);
1053
Hayes Wang3a83ad12012-07-11 20:31:56 +08001054 return RTL_R32(OCPDR);
Hayes Wangc5583862012-07-02 17:23:22 +08001055}
1056
1057#define OCP_STD_PHY_BASE 0xa400
1058
1059static void r8168g_mdio_write(struct rtl8169_private *tp, int reg, int value)
1060{
1061 if (reg == 0x1f) {
1062 tp->ocp_base = value ? value << 4 : OCP_STD_PHY_BASE;
1063 return;
1064 }
1065
1066 if (tp->ocp_base != OCP_STD_PHY_BASE)
1067 reg -= 0x10;
1068
1069 r8168_phy_ocp_write(tp, tp->ocp_base + reg * 2, value);
1070}
1071
1072static int r8168g_mdio_read(struct rtl8169_private *tp, int reg)
1073{
1074 if (tp->ocp_base != OCP_STD_PHY_BASE)
1075 reg -= 0x10;
1076
1077 return r8168_phy_ocp_read(tp, tp->ocp_base + reg * 2);
1078}
1079
Francois Romieuffc46952012-07-06 14:19:23 +02001080DECLARE_RTL_COND(rtl_phyar_cond)
1081{
1082 void __iomem *ioaddr = tp->mmio_addr;
1083
1084 return RTL_R32(PHYAR) & 0x80000000;
1085}
1086
Francois Romieu24192212012-07-06 20:19:42 +02001087static void r8169_mdio_write(struct rtl8169_private *tp, int reg, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088{
Francois Romieu24192212012-07-06 20:19:42 +02001089 void __iomem *ioaddr = tp->mmio_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090
Francois Romieu24192212012-07-06 20:19:42 +02001091 RTL_W32(PHYAR, 0x80000000 | (reg & 0x1f) << 16 | (value & 0xffff));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092
Francois Romieuffc46952012-07-06 14:19:23 +02001093 rtl_udelay_loop_wait_low(tp, &rtl_phyar_cond, 25, 20);
Timo Teräs024a07b2010-06-06 15:38:47 -07001094 /*
Timo Teräs81a95f02010-06-09 17:31:48 -07001095 * According to hardware specs a 20us delay is required after write
1096 * complete indication, but before sending next command.
Timo Teräs024a07b2010-06-06 15:38:47 -07001097 */
Timo Teräs81a95f02010-06-09 17:31:48 -07001098 udelay(20);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099}
1100
Francois Romieu24192212012-07-06 20:19:42 +02001101static int r8169_mdio_read(struct rtl8169_private *tp, int reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102{
Francois Romieu24192212012-07-06 20:19:42 +02001103 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieuffc46952012-07-06 14:19:23 +02001104 int value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105
Francois Romieu24192212012-07-06 20:19:42 +02001106 RTL_W32(PHYAR, 0x0 | (reg & 0x1f) << 16);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107
Francois Romieuffc46952012-07-06 14:19:23 +02001108 value = rtl_udelay_loop_wait_high(tp, &rtl_phyar_cond, 25, 20) ?
1109 RTL_R32(PHYAR) & 0xffff : ~0;
1110
Timo Teräs81a95f02010-06-09 17:31:48 -07001111 /*
1112 * According to hardware specs a 20us delay is required after read
1113 * complete indication, but before sending next command.
1114 */
1115 udelay(20);
1116
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117 return value;
1118}
1119
Francois Romieu24192212012-07-06 20:19:42 +02001120static void r8168dp_1_mdio_access(struct rtl8169_private *tp, int reg, u32 data)
françois romieuc0e45c12011-01-03 15:08:04 +00001121{
Francois Romieu24192212012-07-06 20:19:42 +02001122 void __iomem *ioaddr = tp->mmio_addr;
françois romieuc0e45c12011-01-03 15:08:04 +00001123
Francois Romieu24192212012-07-06 20:19:42 +02001124 RTL_W32(OCPDR, data | ((reg & OCPDR_REG_MASK) << OCPDR_GPHY_REG_SHIFT));
françois romieuc0e45c12011-01-03 15:08:04 +00001125 RTL_W32(OCPAR, OCPAR_GPHY_WRITE_CMD);
1126 RTL_W32(EPHY_RXER_NUM, 0);
1127
Francois Romieuffc46952012-07-06 14:19:23 +02001128 rtl_udelay_loop_wait_low(tp, &rtl_ocpar_cond, 1000, 100);
françois romieuc0e45c12011-01-03 15:08:04 +00001129}
1130
Francois Romieu24192212012-07-06 20:19:42 +02001131static void r8168dp_1_mdio_write(struct rtl8169_private *tp, int reg, int value)
françois romieuc0e45c12011-01-03 15:08:04 +00001132{
Francois Romieu24192212012-07-06 20:19:42 +02001133 r8168dp_1_mdio_access(tp, reg,
1134 OCPDR_WRITE_CMD | (value & OCPDR_DATA_MASK));
françois romieuc0e45c12011-01-03 15:08:04 +00001135}
1136
Francois Romieu24192212012-07-06 20:19:42 +02001137static int r8168dp_1_mdio_read(struct rtl8169_private *tp, int reg)
françois romieuc0e45c12011-01-03 15:08:04 +00001138{
Francois Romieu24192212012-07-06 20:19:42 +02001139 void __iomem *ioaddr = tp->mmio_addr;
françois romieuc0e45c12011-01-03 15:08:04 +00001140
Francois Romieu24192212012-07-06 20:19:42 +02001141 r8168dp_1_mdio_access(tp, reg, OCPDR_READ_CMD);
françois romieuc0e45c12011-01-03 15:08:04 +00001142
1143 mdelay(1);
1144 RTL_W32(OCPAR, OCPAR_GPHY_READ_CMD);
1145 RTL_W32(EPHY_RXER_NUM, 0);
1146
Francois Romieuffc46952012-07-06 14:19:23 +02001147 return rtl_udelay_loop_wait_high(tp, &rtl_ocpar_cond, 1000, 100) ?
1148 RTL_R32(OCPDR) & OCPDR_DATA_MASK : ~0;
françois romieuc0e45c12011-01-03 15:08:04 +00001149}
1150
françois romieue6de30d2011-01-03 15:08:37 +00001151#define R8168DP_1_MDIO_ACCESS_BIT 0x00020000
1152
1153static void r8168dp_2_mdio_start(void __iomem *ioaddr)
1154{
1155 RTL_W32(0xd0, RTL_R32(0xd0) & ~R8168DP_1_MDIO_ACCESS_BIT);
1156}
1157
1158static void r8168dp_2_mdio_stop(void __iomem *ioaddr)
1159{
1160 RTL_W32(0xd0, RTL_R32(0xd0) | R8168DP_1_MDIO_ACCESS_BIT);
1161}
1162
Francois Romieu24192212012-07-06 20:19:42 +02001163static void r8168dp_2_mdio_write(struct rtl8169_private *tp, int reg, int value)
françois romieue6de30d2011-01-03 15:08:37 +00001164{
Francois Romieu24192212012-07-06 20:19:42 +02001165 void __iomem *ioaddr = tp->mmio_addr;
1166
françois romieue6de30d2011-01-03 15:08:37 +00001167 r8168dp_2_mdio_start(ioaddr);
1168
Francois Romieu24192212012-07-06 20:19:42 +02001169 r8169_mdio_write(tp, reg, value);
françois romieue6de30d2011-01-03 15:08:37 +00001170
1171 r8168dp_2_mdio_stop(ioaddr);
1172}
1173
Francois Romieu24192212012-07-06 20:19:42 +02001174static int r8168dp_2_mdio_read(struct rtl8169_private *tp, int reg)
françois romieue6de30d2011-01-03 15:08:37 +00001175{
Francois Romieu24192212012-07-06 20:19:42 +02001176 void __iomem *ioaddr = tp->mmio_addr;
françois romieue6de30d2011-01-03 15:08:37 +00001177 int value;
1178
1179 r8168dp_2_mdio_start(ioaddr);
1180
Francois Romieu24192212012-07-06 20:19:42 +02001181 value = r8169_mdio_read(tp, reg);
françois romieue6de30d2011-01-03 15:08:37 +00001182
1183 r8168dp_2_mdio_stop(ioaddr);
1184
1185 return value;
1186}
1187
françois romieu4da19632011-01-03 15:07:55 +00001188static void rtl_writephy(struct rtl8169_private *tp, int location, u32 val)
Francois Romieudacf8152008-08-02 20:44:13 +02001189{
Francois Romieu24192212012-07-06 20:19:42 +02001190 tp->mdio_ops.write(tp, location, val);
Francois Romieudacf8152008-08-02 20:44:13 +02001191}
1192
françois romieu4da19632011-01-03 15:07:55 +00001193static int rtl_readphy(struct rtl8169_private *tp, int location)
1194{
Francois Romieu24192212012-07-06 20:19:42 +02001195 return tp->mdio_ops.read(tp, location);
françois romieu4da19632011-01-03 15:07:55 +00001196}
1197
1198static void rtl_patchphy(struct rtl8169_private *tp, int reg_addr, int value)
1199{
1200 rtl_writephy(tp, reg_addr, rtl_readphy(tp, reg_addr) | value);
1201}
1202
1203static void rtl_w1w0_phy(struct rtl8169_private *tp, int reg_addr, int p, int m)
françois romieudaf9df62009-10-07 12:44:20 +00001204{
1205 int val;
1206
françois romieu4da19632011-01-03 15:07:55 +00001207 val = rtl_readphy(tp, reg_addr);
1208 rtl_writephy(tp, reg_addr, (val | p) & ~m);
françois romieudaf9df62009-10-07 12:44:20 +00001209}
1210
Francois Romieuccdffb92008-07-26 14:26:06 +02001211static void rtl_mdio_write(struct net_device *dev, int phy_id, int location,
1212 int val)
1213{
1214 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieuccdffb92008-07-26 14:26:06 +02001215
françois romieu4da19632011-01-03 15:07:55 +00001216 rtl_writephy(tp, location, val);
Francois Romieuccdffb92008-07-26 14:26:06 +02001217}
1218
1219static int rtl_mdio_read(struct net_device *dev, int phy_id, int location)
1220{
1221 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieuccdffb92008-07-26 14:26:06 +02001222
françois romieu4da19632011-01-03 15:07:55 +00001223 return rtl_readphy(tp, location);
Francois Romieuccdffb92008-07-26 14:26:06 +02001224}
1225
Francois Romieuffc46952012-07-06 14:19:23 +02001226DECLARE_RTL_COND(rtl_ephyar_cond)
1227{
1228 void __iomem *ioaddr = tp->mmio_addr;
1229
1230 return RTL_R32(EPHYAR) & EPHYAR_FLAG;
1231}
1232
Francois Romieufdf6fc02012-07-06 22:40:38 +02001233static void rtl_ephy_write(struct rtl8169_private *tp, int reg_addr, int value)
Francois Romieudacf8152008-08-02 20:44:13 +02001234{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001235 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieudacf8152008-08-02 20:44:13 +02001236
1237 RTL_W32(EPHYAR, EPHYAR_WRITE_CMD | (value & EPHYAR_DATA_MASK) |
1238 (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT);
1239
Francois Romieuffc46952012-07-06 14:19:23 +02001240 rtl_udelay_loop_wait_low(tp, &rtl_ephyar_cond, 10, 100);
1241
1242 udelay(10);
Francois Romieudacf8152008-08-02 20:44:13 +02001243}
1244
Francois Romieufdf6fc02012-07-06 22:40:38 +02001245static u16 rtl_ephy_read(struct rtl8169_private *tp, int reg_addr)
Francois Romieudacf8152008-08-02 20:44:13 +02001246{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001247 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieudacf8152008-08-02 20:44:13 +02001248
1249 RTL_W32(EPHYAR, (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT);
1250
Francois Romieuffc46952012-07-06 14:19:23 +02001251 return rtl_udelay_loop_wait_high(tp, &rtl_ephyar_cond, 10, 100) ?
1252 RTL_R32(EPHYAR) & EPHYAR_DATA_MASK : ~0;
Francois Romieudacf8152008-08-02 20:44:13 +02001253}
1254
Francois Romieufdf6fc02012-07-06 22:40:38 +02001255static void rtl_eri_write(struct rtl8169_private *tp, int addr, u32 mask,
1256 u32 val, int type)
Hayes Wang133ac402011-07-06 15:58:05 +08001257{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001258 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang133ac402011-07-06 15:58:05 +08001259
1260 BUG_ON((addr & 3) || (mask == 0));
1261 RTL_W32(ERIDR, val);
1262 RTL_W32(ERIAR, ERIAR_WRITE_CMD | type | mask | addr);
1263
Francois Romieuffc46952012-07-06 14:19:23 +02001264 rtl_udelay_loop_wait_low(tp, &rtl_eriar_cond, 100, 100);
Hayes Wang133ac402011-07-06 15:58:05 +08001265}
1266
Francois Romieufdf6fc02012-07-06 22:40:38 +02001267static u32 rtl_eri_read(struct rtl8169_private *tp, int addr, int type)
Hayes Wang133ac402011-07-06 15:58:05 +08001268{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001269 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang133ac402011-07-06 15:58:05 +08001270
1271 RTL_W32(ERIAR, ERIAR_READ_CMD | type | ERIAR_MASK_1111 | addr);
1272
Francois Romieuffc46952012-07-06 14:19:23 +02001273 return rtl_udelay_loop_wait_high(tp, &rtl_eriar_cond, 100, 100) ?
1274 RTL_R32(ERIDR) : ~0;
Hayes Wang133ac402011-07-06 15:58:05 +08001275}
1276
Francois Romieufdf6fc02012-07-06 22:40:38 +02001277static void rtl_w1w0_eri(struct rtl8169_private *tp, int addr, u32 mask, u32 p,
1278 u32 m, int type)
Hayes Wang133ac402011-07-06 15:58:05 +08001279{
1280 u32 val;
1281
Francois Romieufdf6fc02012-07-06 22:40:38 +02001282 val = rtl_eri_read(tp, addr, type);
1283 rtl_eri_write(tp, addr, mask, (val & ~m) | p, type);
Hayes Wang133ac402011-07-06 15:58:05 +08001284}
1285
françois romieuc28aa382011-08-02 03:53:43 +00001286struct exgmac_reg {
1287 u16 addr;
1288 u16 mask;
1289 u32 val;
1290};
1291
Francois Romieufdf6fc02012-07-06 22:40:38 +02001292static void rtl_write_exgmac_batch(struct rtl8169_private *tp,
françois romieuc28aa382011-08-02 03:53:43 +00001293 const struct exgmac_reg *r, int len)
1294{
1295 while (len-- > 0) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001296 rtl_eri_write(tp, r->addr, r->mask, r->val, ERIAR_EXGMAC);
françois romieuc28aa382011-08-02 03:53:43 +00001297 r++;
1298 }
1299}
1300
Francois Romieuffc46952012-07-06 14:19:23 +02001301DECLARE_RTL_COND(rtl_efusear_cond)
1302{
1303 void __iomem *ioaddr = tp->mmio_addr;
1304
1305 return RTL_R32(EFUSEAR) & EFUSEAR_FLAG;
1306}
1307
Francois Romieufdf6fc02012-07-06 22:40:38 +02001308static u8 rtl8168d_efuse_read(struct rtl8169_private *tp, int reg_addr)
françois romieudaf9df62009-10-07 12:44:20 +00001309{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001310 void __iomem *ioaddr = tp->mmio_addr;
françois romieudaf9df62009-10-07 12:44:20 +00001311
1312 RTL_W32(EFUSEAR, (reg_addr & EFUSEAR_REG_MASK) << EFUSEAR_REG_SHIFT);
1313
Francois Romieuffc46952012-07-06 14:19:23 +02001314 return rtl_udelay_loop_wait_high(tp, &rtl_efusear_cond, 100, 300) ?
1315 RTL_R32(EFUSEAR) & EFUSEAR_DATA_MASK : ~0;
françois romieudaf9df62009-10-07 12:44:20 +00001316}
1317
Francois Romieu9085cdfa2012-01-26 12:59:08 +01001318static u16 rtl_get_events(struct rtl8169_private *tp)
1319{
1320 void __iomem *ioaddr = tp->mmio_addr;
1321
1322 return RTL_R16(IntrStatus);
1323}
1324
1325static void rtl_ack_events(struct rtl8169_private *tp, u16 bits)
1326{
1327 void __iomem *ioaddr = tp->mmio_addr;
1328
1329 RTL_W16(IntrStatus, bits);
1330 mmiowb();
1331}
1332
1333static void rtl_irq_disable(struct rtl8169_private *tp)
1334{
1335 void __iomem *ioaddr = tp->mmio_addr;
1336
1337 RTL_W16(IntrMask, 0);
1338 mmiowb();
1339}
1340
Francois Romieu3e990ff2012-01-26 12:50:01 +01001341static void rtl_irq_enable(struct rtl8169_private *tp, u16 bits)
1342{
1343 void __iomem *ioaddr = tp->mmio_addr;
1344
1345 RTL_W16(IntrMask, bits);
1346}
1347
Francois Romieuda78dbf2012-01-26 14:18:23 +01001348#define RTL_EVENT_NAPI_RX (RxOK | RxErr)
1349#define RTL_EVENT_NAPI_TX (TxOK | TxErr)
1350#define RTL_EVENT_NAPI (RTL_EVENT_NAPI_RX | RTL_EVENT_NAPI_TX)
1351
1352static void rtl_irq_enable_all(struct rtl8169_private *tp)
1353{
1354 rtl_irq_enable(tp, RTL_EVENT_NAPI | tp->event_slow);
1355}
1356
françois romieu811fd302011-12-04 20:30:45 +00001357static void rtl8169_irq_mask_and_ack(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358{
françois romieu811fd302011-12-04 20:30:45 +00001359 void __iomem *ioaddr = tp->mmio_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360
Francois Romieu9085cdfa2012-01-26 12:59:08 +01001361 rtl_irq_disable(tp);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001362 rtl_ack_events(tp, RTL_EVENT_NAPI | tp->event_slow);
françois romieu811fd302011-12-04 20:30:45 +00001363 RTL_R8(ChipCmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364}
1365
françois romieu4da19632011-01-03 15:07:55 +00001366static unsigned int rtl8169_tbi_reset_pending(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367{
françois romieu4da19632011-01-03 15:07:55 +00001368 void __iomem *ioaddr = tp->mmio_addr;
1369
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370 return RTL_R32(TBICSR) & TBIReset;
1371}
1372
françois romieu4da19632011-01-03 15:07:55 +00001373static unsigned int rtl8169_xmii_reset_pending(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374{
françois romieu4da19632011-01-03 15:07:55 +00001375 return rtl_readphy(tp, MII_BMCR) & BMCR_RESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376}
1377
1378static unsigned int rtl8169_tbi_link_ok(void __iomem *ioaddr)
1379{
1380 return RTL_R32(TBICSR) & TBILinkOk;
1381}
1382
1383static unsigned int rtl8169_xmii_link_ok(void __iomem *ioaddr)
1384{
1385 return RTL_R8(PHYstatus) & LinkStatus;
1386}
1387
françois romieu4da19632011-01-03 15:07:55 +00001388static void rtl8169_tbi_reset_enable(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389{
françois romieu4da19632011-01-03 15:07:55 +00001390 void __iomem *ioaddr = tp->mmio_addr;
1391
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392 RTL_W32(TBICSR, RTL_R32(TBICSR) | TBIReset);
1393}
1394
françois romieu4da19632011-01-03 15:07:55 +00001395static void rtl8169_xmii_reset_enable(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396{
1397 unsigned int val;
1398
françois romieu4da19632011-01-03 15:07:55 +00001399 val = rtl_readphy(tp, MII_BMCR) | BMCR_RESET;
1400 rtl_writephy(tp, MII_BMCR, val & 0xffff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401}
1402
Hayes Wang70090422011-07-06 15:58:06 +08001403static void rtl_link_chg_patch(struct rtl8169_private *tp)
1404{
1405 void __iomem *ioaddr = tp->mmio_addr;
1406 struct net_device *dev = tp->dev;
1407
1408 if (!netif_running(dev))
1409 return;
1410
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08001411 if (tp->mac_version == RTL_GIGA_MAC_VER_34 ||
1412 tp->mac_version == RTL_GIGA_MAC_VER_38) {
Hayes Wang70090422011-07-06 15:58:06 +08001413 if (RTL_R8(PHYstatus) & _1000bpsF) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001414 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x00000011,
1415 ERIAR_EXGMAC);
1416 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005,
1417 ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08001418 } else if (RTL_R8(PHYstatus) & _100bps) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001419 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f,
1420 ERIAR_EXGMAC);
1421 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005,
1422 ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08001423 } else {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001424 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f,
1425 ERIAR_EXGMAC);
1426 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x0000003f,
1427 ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08001428 }
1429 /* Reset packet filter */
Francois Romieufdf6fc02012-07-06 22:40:38 +02001430 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01,
Hayes Wang70090422011-07-06 15:58:06 +08001431 ERIAR_EXGMAC);
Francois Romieufdf6fc02012-07-06 22:40:38 +02001432 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00,
Hayes Wang70090422011-07-06 15:58:06 +08001433 ERIAR_EXGMAC);
Hayes Wangc2218922011-09-06 16:55:18 +08001434 } else if (tp->mac_version == RTL_GIGA_MAC_VER_35 ||
1435 tp->mac_version == RTL_GIGA_MAC_VER_36) {
1436 if (RTL_R8(PHYstatus) & _1000bpsF) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001437 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x00000011,
1438 ERIAR_EXGMAC);
1439 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005,
1440 ERIAR_EXGMAC);
Hayes Wangc2218922011-09-06 16:55:18 +08001441 } else {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001442 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f,
1443 ERIAR_EXGMAC);
1444 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x0000003f,
1445 ERIAR_EXGMAC);
Hayes Wangc2218922011-09-06 16:55:18 +08001446 }
Hayes Wang7e18dca2012-03-30 14:33:02 +08001447 } else if (tp->mac_version == RTL_GIGA_MAC_VER_37) {
1448 if (RTL_R8(PHYstatus) & _10bps) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001449 rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x4d02,
1450 ERIAR_EXGMAC);
1451 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_0011, 0x0060,
1452 ERIAR_EXGMAC);
Hayes Wang7e18dca2012-03-30 14:33:02 +08001453 } else {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001454 rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000,
1455 ERIAR_EXGMAC);
Hayes Wang7e18dca2012-03-30 14:33:02 +08001456 }
Hayes Wang70090422011-07-06 15:58:06 +08001457 }
1458}
1459
Rafael J. Wysockie4fbce72010-12-08 15:32:14 +00001460static void __rtl8169_check_link_status(struct net_device *dev,
Francois Romieucecb5fd2011-04-01 10:21:07 +02001461 struct rtl8169_private *tp,
1462 void __iomem *ioaddr, bool pm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464 if (tp->link_ok(ioaddr)) {
Hayes Wang70090422011-07-06 15:58:06 +08001465 rtl_link_chg_patch(tp);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001466 /* This is to cancel a scheduled suspend if there's one. */
Rafael J. Wysockie4fbce72010-12-08 15:32:14 +00001467 if (pm)
1468 pm_request_resume(&tp->pci_dev->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469 netif_carrier_on(dev);
Francois Romieu1519e572011-02-03 12:02:36 +01001470 if (net_ratelimit())
1471 netif_info(tp, ifup, dev, "link up\n");
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +02001472 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473 netif_carrier_off(dev);
Joe Perchesbf82c182010-02-09 11:49:50 +00001474 netif_info(tp, ifdown, dev, "link down\n");
Rafael J. Wysockie4fbce72010-12-08 15:32:14 +00001475 if (pm)
hayeswang10953db2011-11-07 20:44:37 +00001476 pm_schedule_suspend(&tp->pci_dev->dev, 5000);
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +02001477 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478}
1479
Rafael J. Wysockie4fbce72010-12-08 15:32:14 +00001480static void rtl8169_check_link_status(struct net_device *dev,
1481 struct rtl8169_private *tp,
1482 void __iomem *ioaddr)
1483{
1484 __rtl8169_check_link_status(dev, tp, ioaddr, false);
1485}
1486
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001487#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST)
1488
1489static u32 __rtl8169_get_wol(struct rtl8169_private *tp)
1490{
1491 void __iomem *ioaddr = tp->mmio_addr;
1492 u8 options;
1493 u32 wolopts = 0;
1494
1495 options = RTL_R8(Config1);
1496 if (!(options & PMEnable))
1497 return 0;
1498
1499 options = RTL_R8(Config3);
1500 if (options & LinkUp)
1501 wolopts |= WAKE_PHY;
1502 if (options & MagicPacket)
1503 wolopts |= WAKE_MAGIC;
1504
1505 options = RTL_R8(Config5);
1506 if (options & UWF)
1507 wolopts |= WAKE_UCAST;
1508 if (options & BWF)
1509 wolopts |= WAKE_BCAST;
1510 if (options & MWF)
1511 wolopts |= WAKE_MCAST;
1512
1513 return wolopts;
1514}
1515
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001516static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
1517{
1518 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001519
Francois Romieuda78dbf2012-01-26 14:18:23 +01001520 rtl_lock_work(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001521
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001522 wol->supported = WAKE_ANY;
1523 wol->wolopts = __rtl8169_get_wol(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001524
Francois Romieuda78dbf2012-01-26 14:18:23 +01001525 rtl_unlock_work(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001526}
1527
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001528static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001529{
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001530 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu07d3f512007-02-21 22:40:46 +01001531 unsigned int i;
Alexey Dobriyan350f7592009-11-25 15:54:21 -08001532 static const struct {
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001533 u32 opt;
1534 u16 reg;
1535 u8 mask;
1536 } cfg[] = {
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001537 { WAKE_PHY, Config3, LinkUp },
1538 { WAKE_MAGIC, Config3, MagicPacket },
1539 { WAKE_UCAST, Config5, UWF },
1540 { WAKE_BCAST, Config5, BWF },
1541 { WAKE_MCAST, Config5, MWF },
1542 { WAKE_ANY, Config5, LanWake }
1543 };
Francois Romieu851e6022012-04-17 11:10:11 +02001544 u8 options;
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001545
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001546 RTL_W8(Cfg9346, Cfg9346_Unlock);
1547
1548 for (i = 0; i < ARRAY_SIZE(cfg); i++) {
Francois Romieu851e6022012-04-17 11:10:11 +02001549 options = RTL_R8(cfg[i].reg) & ~cfg[i].mask;
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001550 if (wolopts & cfg[i].opt)
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001551 options |= cfg[i].mask;
1552 RTL_W8(cfg[i].reg, options);
1553 }
1554
Francois Romieu851e6022012-04-17 11:10:11 +02001555 switch (tp->mac_version) {
1556 case RTL_GIGA_MAC_VER_01 ... RTL_GIGA_MAC_VER_17:
1557 options = RTL_R8(Config1) & ~PMEnable;
1558 if (wolopts)
1559 options |= PMEnable;
1560 RTL_W8(Config1, options);
1561 break;
1562 default:
Francois Romieud387b422012-04-17 11:12:01 +02001563 options = RTL_R8(Config2) & ~PME_SIGNAL;
1564 if (wolopts)
1565 options |= PME_SIGNAL;
1566 RTL_W8(Config2, options);
Francois Romieu851e6022012-04-17 11:10:11 +02001567 break;
1568 }
1569
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001570 RTL_W8(Cfg9346, Cfg9346_Lock);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001571}
1572
1573static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
1574{
1575 struct rtl8169_private *tp = netdev_priv(dev);
1576
Francois Romieuda78dbf2012-01-26 14:18:23 +01001577 rtl_lock_work(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001578
Francois Romieuf23e7fd2007-10-04 22:36:14 +02001579 if (wol->wolopts)
1580 tp->features |= RTL_FEATURE_WOL;
1581 else
1582 tp->features &= ~RTL_FEATURE_WOL;
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001583 __rtl8169_set_wol(tp, wol->wolopts);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001584
1585 rtl_unlock_work(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001586
françois romieuea809072010-11-08 13:23:58 +00001587 device_set_wakeup_enable(&tp->pci_dev->dev, wol->wolopts);
1588
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001589 return 0;
1590}
1591
Francois Romieu31bd2042011-04-26 18:58:59 +02001592static const char *rtl_lookup_firmware_name(struct rtl8169_private *tp)
1593{
Francois Romieu85bffe62011-04-27 08:22:39 +02001594 return rtl_chip_infos[tp->mac_version].fw_name;
Francois Romieu31bd2042011-04-26 18:58:59 +02001595}
1596
Linus Torvalds1da177e2005-04-16 15:20:36 -07001597static void rtl8169_get_drvinfo(struct net_device *dev,
1598 struct ethtool_drvinfo *info)
1599{
1600 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieub6ffd972011-06-17 17:00:05 +02001601 struct rtl_fw *rtl_fw = tp->rtl_fw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602
Rick Jones68aad782011-11-07 13:29:27 +00001603 strlcpy(info->driver, MODULENAME, sizeof(info->driver));
1604 strlcpy(info->version, RTL8169_VERSION, sizeof(info->version));
1605 strlcpy(info->bus_info, pci_name(tp->pci_dev), sizeof(info->bus_info));
Francois Romieu1c361ef2011-06-17 17:16:24 +02001606 BUILD_BUG_ON(sizeof(info->fw_version) < sizeof(rtl_fw->version));
Rick Jones8ac72d12011-11-22 14:06:26 +00001607 if (!IS_ERR_OR_NULL(rtl_fw))
1608 strlcpy(info->fw_version, rtl_fw->version,
1609 sizeof(info->fw_version));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610}
1611
1612static int rtl8169_get_regs_len(struct net_device *dev)
1613{
1614 return R8169_REGS_SIZE;
1615}
1616
1617static int rtl8169_set_speed_tbi(struct net_device *dev,
Oliver Neukum54405cd2011-01-06 21:55:13 +01001618 u8 autoneg, u16 speed, u8 duplex, u32 ignored)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001619{
1620 struct rtl8169_private *tp = netdev_priv(dev);
1621 void __iomem *ioaddr = tp->mmio_addr;
1622 int ret = 0;
1623 u32 reg;
1624
1625 reg = RTL_R32(TBICSR);
1626 if ((autoneg == AUTONEG_DISABLE) && (speed == SPEED_1000) &&
1627 (duplex == DUPLEX_FULL)) {
1628 RTL_W32(TBICSR, reg & ~(TBINwEnable | TBINwRestart));
1629 } else if (autoneg == AUTONEG_ENABLE)
1630 RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart);
1631 else {
Joe Perchesbf82c182010-02-09 11:49:50 +00001632 netif_warn(tp, link, dev,
1633 "incorrect speed setting refused in TBI mode\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634 ret = -EOPNOTSUPP;
1635 }
1636
1637 return ret;
1638}
1639
1640static int rtl8169_set_speed_xmii(struct net_device *dev,
Oliver Neukum54405cd2011-01-06 21:55:13 +01001641 u8 autoneg, u16 speed, u8 duplex, u32 adv)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001642{
1643 struct rtl8169_private *tp = netdev_priv(dev);
françois romieu3577aa12009-05-19 10:46:48 +00001644 int giga_ctrl, bmcr;
Oliver Neukum54405cd2011-01-06 21:55:13 +01001645 int rc = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646
Hayes Wang716b50a2011-02-22 17:26:18 +08001647 rtl_writephy(tp, 0x1f, 0x0000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001648
1649 if (autoneg == AUTONEG_ENABLE) {
françois romieu3577aa12009-05-19 10:46:48 +00001650 int auto_nego;
1651
françois romieu4da19632011-01-03 15:07:55 +00001652 auto_nego = rtl_readphy(tp, MII_ADVERTISE);
Oliver Neukum54405cd2011-01-06 21:55:13 +01001653 auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL |
1654 ADVERTISE_100HALF | ADVERTISE_100FULL);
1655
1656 if (adv & ADVERTISED_10baseT_Half)
1657 auto_nego |= ADVERTISE_10HALF;
1658 if (adv & ADVERTISED_10baseT_Full)
1659 auto_nego |= ADVERTISE_10FULL;
1660 if (adv & ADVERTISED_100baseT_Half)
1661 auto_nego |= ADVERTISE_100HALF;
1662 if (adv & ADVERTISED_100baseT_Full)
1663 auto_nego |= ADVERTISE_100FULL;
1664
françois romieu3577aa12009-05-19 10:46:48 +00001665 auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
1666
françois romieu4da19632011-01-03 15:07:55 +00001667 giga_ctrl = rtl_readphy(tp, MII_CTRL1000);
françois romieu3577aa12009-05-19 10:46:48 +00001668 giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
1669
1670 /* The 8100e/8101e/8102e do Fast Ethernet only. */
Francois Romieu826e6cb2011-03-11 20:30:24 +01001671 if (tp->mii.supports_gmii) {
Oliver Neukum54405cd2011-01-06 21:55:13 +01001672 if (adv & ADVERTISED_1000baseT_Half)
1673 giga_ctrl |= ADVERTISE_1000HALF;
1674 if (adv & ADVERTISED_1000baseT_Full)
1675 giga_ctrl |= ADVERTISE_1000FULL;
1676 } else if (adv & (ADVERTISED_1000baseT_Half |
1677 ADVERTISED_1000baseT_Full)) {
Joe Perchesbf82c182010-02-09 11:49:50 +00001678 netif_info(tp, link, dev,
1679 "PHY does not support 1000Mbps\n");
Oliver Neukum54405cd2011-01-06 21:55:13 +01001680 goto out;
Francois Romieubcf0bf92006-07-26 23:14:13 +02001681 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682
françois romieu3577aa12009-05-19 10:46:48 +00001683 bmcr = BMCR_ANENABLE | BMCR_ANRESTART;
Francois Romieu623a1592006-05-14 12:42:14 +02001684
françois romieu4da19632011-01-03 15:07:55 +00001685 rtl_writephy(tp, MII_ADVERTISE, auto_nego);
1686 rtl_writephy(tp, MII_CTRL1000, giga_ctrl);
françois romieu3577aa12009-05-19 10:46:48 +00001687 } else {
1688 giga_ctrl = 0;
1689
1690 if (speed == SPEED_10)
1691 bmcr = 0;
1692 else if (speed == SPEED_100)
1693 bmcr = BMCR_SPEED100;
1694 else
Oliver Neukum54405cd2011-01-06 21:55:13 +01001695 goto out;
françois romieu3577aa12009-05-19 10:46:48 +00001696
1697 if (duplex == DUPLEX_FULL)
1698 bmcr |= BMCR_FULLDPLX;
Roger So2584fbc2007-07-31 23:52:42 +02001699 }
1700
françois romieu4da19632011-01-03 15:07:55 +00001701 rtl_writephy(tp, MII_BMCR, bmcr);
françois romieu3577aa12009-05-19 10:46:48 +00001702
Francois Romieucecb5fd2011-04-01 10:21:07 +02001703 if (tp->mac_version == RTL_GIGA_MAC_VER_02 ||
1704 tp->mac_version == RTL_GIGA_MAC_VER_03) {
françois romieu3577aa12009-05-19 10:46:48 +00001705 if ((speed == SPEED_100) && (autoneg != AUTONEG_ENABLE)) {
françois romieu4da19632011-01-03 15:07:55 +00001706 rtl_writephy(tp, 0x17, 0x2138);
1707 rtl_writephy(tp, 0x0e, 0x0260);
françois romieu3577aa12009-05-19 10:46:48 +00001708 } else {
françois romieu4da19632011-01-03 15:07:55 +00001709 rtl_writephy(tp, 0x17, 0x2108);
1710 rtl_writephy(tp, 0x0e, 0x0000);
françois romieu3577aa12009-05-19 10:46:48 +00001711 }
1712 }
1713
Oliver Neukum54405cd2011-01-06 21:55:13 +01001714 rc = 0;
1715out:
1716 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001717}
1718
1719static int rtl8169_set_speed(struct net_device *dev,
Oliver Neukum54405cd2011-01-06 21:55:13 +01001720 u8 autoneg, u16 speed, u8 duplex, u32 advertising)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721{
1722 struct rtl8169_private *tp = netdev_priv(dev);
1723 int ret;
1724
Oliver Neukum54405cd2011-01-06 21:55:13 +01001725 ret = tp->set_speed(dev, autoneg, speed, duplex, advertising);
Francois Romieu4876cc12011-03-11 21:07:11 +01001726 if (ret < 0)
1727 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728
Francois Romieu4876cc12011-03-11 21:07:11 +01001729 if (netif_running(dev) && (autoneg == AUTONEG_ENABLE) &&
1730 (advertising & ADVERTISED_1000baseT_Full)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731 mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT);
Francois Romieu4876cc12011-03-11 21:07:11 +01001732 }
1733out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001734 return ret;
1735}
1736
1737static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
1738{
1739 struct rtl8169_private *tp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740 int ret;
1741
Francois Romieu4876cc12011-03-11 21:07:11 +01001742 del_timer_sync(&tp->timer);
1743
Francois Romieuda78dbf2012-01-26 14:18:23 +01001744 rtl_lock_work(tp);
Francois Romieucecb5fd2011-04-01 10:21:07 +02001745 ret = rtl8169_set_speed(dev, cmd->autoneg, ethtool_cmd_speed(cmd),
David Decotigny25db0332011-04-27 18:32:39 +00001746 cmd->duplex, cmd->advertising);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001747 rtl_unlock_work(tp);
Francois Romieu5b0384f2006-08-16 16:00:01 +02001748
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749 return ret;
1750}
1751
Michał Mirosławc8f44af2011-11-15 15:29:55 +00001752static netdev_features_t rtl8169_fix_features(struct net_device *dev,
1753 netdev_features_t features)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754{
Francois Romieud58d46b2011-05-03 16:38:29 +02001755 struct rtl8169_private *tp = netdev_priv(dev);
1756
Francois Romieu2b7b4312011-04-18 22:53:24 -07001757 if (dev->mtu > TD_MSS_MAX)
Michał Mirosław350fb322011-04-08 06:35:56 +00001758 features &= ~NETIF_F_ALL_TSO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001759
Francois Romieud58d46b2011-05-03 16:38:29 +02001760 if (dev->mtu > JUMBO_1K &&
1761 !rtl_chip_infos[tp->mac_version].jumbo_tx_csum)
1762 features &= ~NETIF_F_IP_CSUM;
1763
Michał Mirosław350fb322011-04-08 06:35:56 +00001764 return features;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001765}
1766
Francois Romieuda78dbf2012-01-26 14:18:23 +01001767static void __rtl8169_set_features(struct net_device *dev,
1768 netdev_features_t features)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001769{
1770 struct rtl8169_private *tp = netdev_priv(dev);
Ben Greear6bbe0212012-02-10 15:04:33 +00001771 netdev_features_t changed = features ^ dev->features;
Francois Romieuda78dbf2012-01-26 14:18:23 +01001772 void __iomem *ioaddr = tp->mmio_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001773
Ben Greear6bbe0212012-02-10 15:04:33 +00001774 if (!(changed & (NETIF_F_RXALL | NETIF_F_RXCSUM | NETIF_F_HW_VLAN_RX)))
1775 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001776
Ben Greear6bbe0212012-02-10 15:04:33 +00001777 if (changed & (NETIF_F_RXCSUM | NETIF_F_HW_VLAN_RX)) {
1778 if (features & NETIF_F_RXCSUM)
1779 tp->cp_cmd |= RxChkSum;
1780 else
1781 tp->cp_cmd &= ~RxChkSum;
Michał Mirosław350fb322011-04-08 06:35:56 +00001782
Ben Greear6bbe0212012-02-10 15:04:33 +00001783 if (dev->features & NETIF_F_HW_VLAN_RX)
1784 tp->cp_cmd |= RxVlan;
1785 else
1786 tp->cp_cmd &= ~RxVlan;
1787
1788 RTL_W16(CPlusCmd, tp->cp_cmd);
1789 RTL_R16(CPlusCmd);
1790 }
1791 if (changed & NETIF_F_RXALL) {
1792 int tmp = (RTL_R32(RxConfig) & ~(AcceptErr | AcceptRunt));
1793 if (features & NETIF_F_RXALL)
1794 tmp |= (AcceptErr | AcceptRunt);
1795 RTL_W32(RxConfig, tmp);
1796 }
Francois Romieuda78dbf2012-01-26 14:18:23 +01001797}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001798
Francois Romieuda78dbf2012-01-26 14:18:23 +01001799static int rtl8169_set_features(struct net_device *dev,
1800 netdev_features_t features)
1801{
1802 struct rtl8169_private *tp = netdev_priv(dev);
1803
1804 rtl_lock_work(tp);
1805 __rtl8169_set_features(dev, features);
1806 rtl_unlock_work(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001807
1808 return 0;
1809}
1810
Francois Romieuda78dbf2012-01-26 14:18:23 +01001811
Kirill Smelkov810f4892012-11-10 21:11:02 +04001812static inline u32 rtl8169_tx_vlan_tag(struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001813{
Jesse Grosseab6d182010-10-20 13:56:03 +00001814 return (vlan_tx_tag_present(skb)) ?
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815 TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00;
1816}
1817
Francois Romieu7a8fc772011-03-01 17:18:33 +01001818static void rtl8169_rx_vlan_tag(struct RxDesc *desc, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001819{
1820 u32 opts2 = le32_to_cpu(desc->opts2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001821
Francois Romieu7a8fc772011-03-01 17:18:33 +01001822 if (opts2 & RxVlanTag)
1823 __vlan_hwaccel_put_tag(skb, swab16(opts2 & 0xffff));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001824}
1825
Francois Romieuccdffb92008-07-26 14:26:06 +02001826static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001827{
1828 struct rtl8169_private *tp = netdev_priv(dev);
1829 void __iomem *ioaddr = tp->mmio_addr;
1830 u32 status;
1831
1832 cmd->supported =
1833 SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE;
1834 cmd->port = PORT_FIBRE;
1835 cmd->transceiver = XCVR_INTERNAL;
1836
1837 status = RTL_R32(TBICSR);
1838 cmd->advertising = (status & TBINwEnable) ? ADVERTISED_Autoneg : 0;
1839 cmd->autoneg = !!(status & TBINwEnable);
1840
David Decotigny70739492011-04-27 18:32:40 +00001841 ethtool_cmd_speed_set(cmd, SPEED_1000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842 cmd->duplex = DUPLEX_FULL; /* Always set */
Francois Romieuccdffb92008-07-26 14:26:06 +02001843
1844 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001845}
1846
Francois Romieuccdffb92008-07-26 14:26:06 +02001847static int rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001848{
1849 struct rtl8169_private *tp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001850
Francois Romieuccdffb92008-07-26 14:26:06 +02001851 return mii_ethtool_gset(&tp->mii, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852}
1853
1854static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
1855{
1856 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieuccdffb92008-07-26 14:26:06 +02001857 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858
Francois Romieuda78dbf2012-01-26 14:18:23 +01001859 rtl_lock_work(tp);
Francois Romieuccdffb92008-07-26 14:26:06 +02001860 rc = tp->get_settings(dev, cmd);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001861 rtl_unlock_work(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862
Francois Romieuccdffb92008-07-26 14:26:06 +02001863 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864}
1865
1866static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs,
1867 void *p)
1868{
Francois Romieu5b0384f2006-08-16 16:00:01 +02001869 struct rtl8169_private *tp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001870
Francois Romieu5b0384f2006-08-16 16:00:01 +02001871 if (regs->len > R8169_REGS_SIZE)
1872 regs->len = R8169_REGS_SIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001873
Francois Romieuda78dbf2012-01-26 14:18:23 +01001874 rtl_lock_work(tp);
Francois Romieu5b0384f2006-08-16 16:00:01 +02001875 memcpy_fromio(p, tp->mmio_addr, regs->len);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001876 rtl_unlock_work(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877}
1878
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +02001879static u32 rtl8169_get_msglevel(struct net_device *dev)
1880{
1881 struct rtl8169_private *tp = netdev_priv(dev);
1882
1883 return tp->msg_enable;
1884}
1885
1886static void rtl8169_set_msglevel(struct net_device *dev, u32 value)
1887{
1888 struct rtl8169_private *tp = netdev_priv(dev);
1889
1890 tp->msg_enable = value;
1891}
1892
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001893static const char rtl8169_gstrings[][ETH_GSTRING_LEN] = {
1894 "tx_packets",
1895 "rx_packets",
1896 "tx_errors",
1897 "rx_errors",
1898 "rx_missed",
1899 "align_errors",
1900 "tx_single_collisions",
1901 "tx_multi_collisions",
1902 "unicast",
1903 "broadcast",
1904 "multicast",
1905 "tx_aborted",
1906 "tx_underrun",
1907};
1908
Jeff Garzikb9f2c042007-10-03 18:07:32 -07001909static int rtl8169_get_sset_count(struct net_device *dev, int sset)
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001910{
Jeff Garzikb9f2c042007-10-03 18:07:32 -07001911 switch (sset) {
1912 case ETH_SS_STATS:
1913 return ARRAY_SIZE(rtl8169_gstrings);
1914 default:
1915 return -EOPNOTSUPP;
1916 }
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001917}
1918
Francois Romieuffc46952012-07-06 14:19:23 +02001919DECLARE_RTL_COND(rtl_counters_cond)
1920{
1921 void __iomem *ioaddr = tp->mmio_addr;
1922
1923 return RTL_R32(CounterAddrLow) & CounterDump;
1924}
1925
Ivan Vecera355423d2009-02-06 21:49:57 -08001926static void rtl8169_update_counters(struct net_device *dev)
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001927{
1928 struct rtl8169_private *tp = netdev_priv(dev);
1929 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieucecb5fd2011-04-01 10:21:07 +02001930 struct device *d = &tp->pci_dev->dev;
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001931 struct rtl8169_counters *counters;
1932 dma_addr_t paddr;
1933 u32 cmd;
1934
Ivan Vecera355423d2009-02-06 21:49:57 -08001935 /*
1936 * Some chips are unable to dump tally counters when the receiver
1937 * is disabled.
1938 */
1939 if ((RTL_R8(ChipCmd) & CmdRxEnb) == 0)
1940 return;
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001941
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00001942 counters = dma_alloc_coherent(d, sizeof(*counters), &paddr, GFP_KERNEL);
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001943 if (!counters)
1944 return;
1945
1946 RTL_W32(CounterAddrHigh, (u64)paddr >> 32);
Yang Hongyang284901a2009-04-06 19:01:15 -07001947 cmd = (u64)paddr & DMA_BIT_MASK(32);
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001948 RTL_W32(CounterAddrLow, cmd);
1949 RTL_W32(CounterAddrLow, cmd | CounterDump);
1950
Francois Romieuffc46952012-07-06 14:19:23 +02001951 if (rtl_udelay_loop_wait_low(tp, &rtl_counters_cond, 10, 1000))
1952 memcpy(&tp->counters, counters, sizeof(*counters));
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001953
1954 RTL_W32(CounterAddrLow, 0);
1955 RTL_W32(CounterAddrHigh, 0);
1956
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00001957 dma_free_coherent(d, sizeof(*counters), counters, paddr);
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001958}
1959
Ivan Vecera355423d2009-02-06 21:49:57 -08001960static void rtl8169_get_ethtool_stats(struct net_device *dev,
1961 struct ethtool_stats *stats, u64 *data)
1962{
1963 struct rtl8169_private *tp = netdev_priv(dev);
1964
1965 ASSERT_RTNL();
1966
1967 rtl8169_update_counters(dev);
1968
1969 data[0] = le64_to_cpu(tp->counters.tx_packets);
1970 data[1] = le64_to_cpu(tp->counters.rx_packets);
1971 data[2] = le64_to_cpu(tp->counters.tx_errors);
1972 data[3] = le32_to_cpu(tp->counters.rx_errors);
1973 data[4] = le16_to_cpu(tp->counters.rx_missed);
1974 data[5] = le16_to_cpu(tp->counters.align_errors);
1975 data[6] = le32_to_cpu(tp->counters.tx_one_collision);
1976 data[7] = le32_to_cpu(tp->counters.tx_multi_collision);
1977 data[8] = le64_to_cpu(tp->counters.rx_unicast);
1978 data[9] = le64_to_cpu(tp->counters.rx_broadcast);
1979 data[10] = le32_to_cpu(tp->counters.rx_multicast);
1980 data[11] = le16_to_cpu(tp->counters.tx_aborted);
1981 data[12] = le16_to_cpu(tp->counters.tx_underun);
1982}
1983
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001984static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data)
1985{
1986 switch(stringset) {
1987 case ETH_SS_STATS:
1988 memcpy(data, *rtl8169_gstrings, sizeof(rtl8169_gstrings));
1989 break;
1990 }
1991}
1992
Jeff Garzik7282d492006-09-13 14:30:00 -04001993static const struct ethtool_ops rtl8169_ethtool_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994 .get_drvinfo = rtl8169_get_drvinfo,
1995 .get_regs_len = rtl8169_get_regs_len,
1996 .get_link = ethtool_op_get_link,
1997 .get_settings = rtl8169_get_settings,
1998 .set_settings = rtl8169_set_settings,
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +02001999 .get_msglevel = rtl8169_get_msglevel,
2000 .set_msglevel = rtl8169_set_msglevel,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001 .get_regs = rtl8169_get_regs,
Francois Romieu61a4dcc2006-02-23 00:55:25 +01002002 .get_wol = rtl8169_get_wol,
2003 .set_wol = rtl8169_set_wol,
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02002004 .get_strings = rtl8169_get_strings,
Jeff Garzikb9f2c042007-10-03 18:07:32 -07002005 .get_sset_count = rtl8169_get_sset_count,
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02002006 .get_ethtool_stats = rtl8169_get_ethtool_stats,
Richard Cochrane1593bb2012-04-03 22:59:35 +00002007 .get_ts_info = ethtool_op_get_ts_info,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002008};
2009
Francois Romieu07d3f512007-02-21 22:40:46 +01002010static void rtl8169_get_mac_version(struct rtl8169_private *tp,
Francois Romieu5d320a22011-05-08 17:47:36 +02002011 struct net_device *dev, u8 default_version)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002012{
Francois Romieu5d320a22011-05-08 17:47:36 +02002013 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu0e485152007-02-20 00:00:26 +01002014 /*
2015 * The driver currently handles the 8168Bf and the 8168Be identically
2016 * but they can be identified more specifically through the test below
2017 * if needed:
2018 *
2019 * (RTL_R32(TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be
Francois Romieu01272152007-02-20 22:58:51 +01002020 *
2021 * Same thing for the 8101Eb and the 8101Ec:
2022 *
2023 * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec
Francois Romieu0e485152007-02-20 00:00:26 +01002024 */
Francois Romieu37441002011-06-17 22:58:54 +02002025 static const struct rtl_mac_info {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002026 u32 mask;
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002027 u32 val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002028 int mac_version;
2029 } mac_info[] = {
Hayes Wangc5583862012-07-02 17:23:22 +08002030 /* 8168G family. */
2031 { 0x7cf00000, 0x4c100000, RTL_GIGA_MAC_VER_41 },
2032 { 0x7cf00000, 0x4c000000, RTL_GIGA_MAC_VER_40 },
2033
Hayes Wangc2218922011-09-06 16:55:18 +08002034 /* 8168F family. */
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08002035 { 0x7c800000, 0x48800000, RTL_GIGA_MAC_VER_38 },
Hayes Wangc2218922011-09-06 16:55:18 +08002036 { 0x7cf00000, 0x48100000, RTL_GIGA_MAC_VER_36 },
2037 { 0x7cf00000, 0x48000000, RTL_GIGA_MAC_VER_35 },
2038
hayeswang01dc7fe2011-03-21 01:50:28 +00002039 /* 8168E family. */
Hayes Wang70090422011-07-06 15:58:06 +08002040 { 0x7c800000, 0x2c800000, RTL_GIGA_MAC_VER_34 },
hayeswang01dc7fe2011-03-21 01:50:28 +00002041 { 0x7cf00000, 0x2c200000, RTL_GIGA_MAC_VER_33 },
2042 { 0x7cf00000, 0x2c100000, RTL_GIGA_MAC_VER_32 },
2043 { 0x7c800000, 0x2c000000, RTL_GIGA_MAC_VER_33 },
2044
Francois Romieu5b538df2008-07-20 16:22:45 +02002045 /* 8168D family. */
françois romieudaf9df62009-10-07 12:44:20 +00002046 { 0x7cf00000, 0x28300000, RTL_GIGA_MAC_VER_26 },
2047 { 0x7cf00000, 0x28100000, RTL_GIGA_MAC_VER_25 },
françois romieudaf9df62009-10-07 12:44:20 +00002048 { 0x7c800000, 0x28000000, RTL_GIGA_MAC_VER_26 },
Francois Romieu5b538df2008-07-20 16:22:45 +02002049
françois romieue6de30d2011-01-03 15:08:37 +00002050 /* 8168DP family. */
2051 { 0x7cf00000, 0x28800000, RTL_GIGA_MAC_VER_27 },
2052 { 0x7cf00000, 0x28a00000, RTL_GIGA_MAC_VER_28 },
hayeswang4804b3b2011-03-21 01:50:29 +00002053 { 0x7cf00000, 0x28b00000, RTL_GIGA_MAC_VER_31 },
françois romieue6de30d2011-01-03 15:08:37 +00002054
Francois Romieuef808d52008-06-29 13:10:54 +02002055 /* 8168C family. */
Francois Romieu17c99292010-07-11 17:10:09 -07002056 { 0x7cf00000, 0x3cb00000, RTL_GIGA_MAC_VER_24 },
Francois Romieuef3386f2008-06-29 12:24:30 +02002057 { 0x7cf00000, 0x3c900000, RTL_GIGA_MAC_VER_23 },
Francois Romieuef808d52008-06-29 13:10:54 +02002058 { 0x7cf00000, 0x3c800000, RTL_GIGA_MAC_VER_18 },
Francois Romieu7f3e3d32008-07-20 18:53:20 +02002059 { 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_24 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002060 { 0x7cf00000, 0x3c000000, RTL_GIGA_MAC_VER_19 },
2061 { 0x7cf00000, 0x3c200000, RTL_GIGA_MAC_VER_20 },
Francois Romieu197ff762008-06-28 13:16:02 +02002062 { 0x7cf00000, 0x3c300000, RTL_GIGA_MAC_VER_21 },
Francois Romieu6fb07052008-06-29 11:54:28 +02002063 { 0x7cf00000, 0x3c400000, RTL_GIGA_MAC_VER_22 },
Francois Romieuef808d52008-06-29 13:10:54 +02002064 { 0x7c800000, 0x3c000000, RTL_GIGA_MAC_VER_22 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002065
2066 /* 8168B family. */
2067 { 0x7cf00000, 0x38000000, RTL_GIGA_MAC_VER_12 },
2068 { 0x7cf00000, 0x38500000, RTL_GIGA_MAC_VER_17 },
2069 { 0x7c800000, 0x38000000, RTL_GIGA_MAC_VER_17 },
2070 { 0x7c800000, 0x30000000, RTL_GIGA_MAC_VER_11 },
2071
2072 /* 8101 family. */
Hayes Wang5598bfe2012-07-02 17:23:21 +08002073 { 0x7cf00000, 0x44900000, RTL_GIGA_MAC_VER_39 },
2074 { 0x7c800000, 0x44800000, RTL_GIGA_MAC_VER_39 },
Hayes Wang7e18dca2012-03-30 14:33:02 +08002075 { 0x7c800000, 0x44000000, RTL_GIGA_MAC_VER_37 },
hayeswang36a0e6c2011-03-21 01:50:30 +00002076 { 0x7cf00000, 0x40b00000, RTL_GIGA_MAC_VER_30 },
Hayes Wang5a5e4442011-02-22 17:26:21 +08002077 { 0x7cf00000, 0x40a00000, RTL_GIGA_MAC_VER_30 },
2078 { 0x7cf00000, 0x40900000, RTL_GIGA_MAC_VER_29 },
2079 { 0x7c800000, 0x40800000, RTL_GIGA_MAC_VER_30 },
Francois Romieu2857ffb2008-08-02 21:08:49 +02002080 { 0x7cf00000, 0x34a00000, RTL_GIGA_MAC_VER_09 },
2081 { 0x7cf00000, 0x24a00000, RTL_GIGA_MAC_VER_09 },
2082 { 0x7cf00000, 0x34900000, RTL_GIGA_MAC_VER_08 },
2083 { 0x7cf00000, 0x24900000, RTL_GIGA_MAC_VER_08 },
2084 { 0x7cf00000, 0x34800000, RTL_GIGA_MAC_VER_07 },
2085 { 0x7cf00000, 0x24800000, RTL_GIGA_MAC_VER_07 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002086 { 0x7cf00000, 0x34000000, RTL_GIGA_MAC_VER_13 },
Francois Romieu2857ffb2008-08-02 21:08:49 +02002087 { 0x7cf00000, 0x34300000, RTL_GIGA_MAC_VER_10 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002088 { 0x7cf00000, 0x34200000, RTL_GIGA_MAC_VER_16 },
Francois Romieu2857ffb2008-08-02 21:08:49 +02002089 { 0x7c800000, 0x34800000, RTL_GIGA_MAC_VER_09 },
2090 { 0x7c800000, 0x24800000, RTL_GIGA_MAC_VER_09 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002091 { 0x7c800000, 0x34000000, RTL_GIGA_MAC_VER_16 },
2092 /* FIXME: where did these entries come from ? -- FR */
2093 { 0xfc800000, 0x38800000, RTL_GIGA_MAC_VER_15 },
2094 { 0xfc800000, 0x30800000, RTL_GIGA_MAC_VER_14 },
2095
2096 /* 8110 family. */
2097 { 0xfc800000, 0x98000000, RTL_GIGA_MAC_VER_06 },
2098 { 0xfc800000, 0x18000000, RTL_GIGA_MAC_VER_05 },
2099 { 0xfc800000, 0x10000000, RTL_GIGA_MAC_VER_04 },
2100 { 0xfc800000, 0x04000000, RTL_GIGA_MAC_VER_03 },
2101 { 0xfc800000, 0x00800000, RTL_GIGA_MAC_VER_02 },
2102 { 0xfc800000, 0x00000000, RTL_GIGA_MAC_VER_01 },
2103
Jean Delvaref21b75e2009-05-26 20:54:48 -07002104 /* Catch-all */
2105 { 0x00000000, 0x00000000, RTL_GIGA_MAC_NONE }
Francois Romieu37441002011-06-17 22:58:54 +02002106 };
2107 const struct rtl_mac_info *p = mac_info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002108 u32 reg;
2109
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002110 reg = RTL_R32(TxConfig);
2111 while ((reg & p->mask) != p->val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002112 p++;
2113 tp->mac_version = p->mac_version;
Francois Romieu5d320a22011-05-08 17:47:36 +02002114
2115 if (tp->mac_version == RTL_GIGA_MAC_NONE) {
2116 netif_notice(tp, probe, dev,
2117 "unknown MAC, using family default\n");
2118 tp->mac_version = default_version;
2119 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002120}
2121
2122static void rtl8169_print_mac_version(struct rtl8169_private *tp)
2123{
Francois Romieubcf0bf92006-07-26 23:14:13 +02002124 dprintk("mac_version = 0x%02x\n", tp->mac_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002125}
2126
Francois Romieu867763c2007-08-17 18:21:58 +02002127struct phy_reg {
2128 u16 reg;
2129 u16 val;
2130};
2131
françois romieu4da19632011-01-03 15:07:55 +00002132static void rtl_writephy_batch(struct rtl8169_private *tp,
2133 const struct phy_reg *regs, int len)
Francois Romieu867763c2007-08-17 18:21:58 +02002134{
2135 while (len-- > 0) {
françois romieu4da19632011-01-03 15:07:55 +00002136 rtl_writephy(tp, regs->reg, regs->val);
Francois Romieu867763c2007-08-17 18:21:58 +02002137 regs++;
2138 }
2139}
2140
françois romieubca03d52011-01-03 15:07:31 +00002141#define PHY_READ 0x00000000
2142#define PHY_DATA_OR 0x10000000
2143#define PHY_DATA_AND 0x20000000
2144#define PHY_BJMPN 0x30000000
2145#define PHY_READ_EFUSE 0x40000000
2146#define PHY_READ_MAC_BYTE 0x50000000
2147#define PHY_WRITE_MAC_BYTE 0x60000000
2148#define PHY_CLEAR_READCOUNT 0x70000000
2149#define PHY_WRITE 0x80000000
2150#define PHY_READCOUNT_EQ_SKIP 0x90000000
2151#define PHY_COMP_EQ_SKIPN 0xa0000000
2152#define PHY_COMP_NEQ_SKIPN 0xb0000000
2153#define PHY_WRITE_PREVIOUS 0xc0000000
2154#define PHY_SKIPN 0xd0000000
2155#define PHY_DELAY_MS 0xe0000000
2156#define PHY_WRITE_ERI_WORD 0xf0000000
2157
Hayes Wang960aee62011-06-18 11:37:48 +02002158struct fw_info {
2159 u32 magic;
2160 char version[RTL_VER_SIZE];
2161 __le32 fw_start;
2162 __le32 fw_len;
2163 u8 chksum;
2164} __packed;
2165
Francois Romieu1c361ef2011-06-17 17:16:24 +02002166#define FW_OPCODE_SIZE sizeof(typeof(*((struct rtl_fw_phy_action *)0)->code))
2167
2168static bool rtl_fw_format_ok(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
françois romieubca03d52011-01-03 15:07:31 +00002169{
Francois Romieub6ffd972011-06-17 17:00:05 +02002170 const struct firmware *fw = rtl_fw->fw;
Hayes Wang960aee62011-06-18 11:37:48 +02002171 struct fw_info *fw_info = (struct fw_info *)fw->data;
Francois Romieu1c361ef2011-06-17 17:16:24 +02002172 struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
2173 char *version = rtl_fw->version;
2174 bool rc = false;
françois romieubca03d52011-01-03 15:07:31 +00002175
Francois Romieu1c361ef2011-06-17 17:16:24 +02002176 if (fw->size < FW_OPCODE_SIZE)
2177 goto out;
Hayes Wang960aee62011-06-18 11:37:48 +02002178
2179 if (!fw_info->magic) {
2180 size_t i, size, start;
2181 u8 checksum = 0;
2182
2183 if (fw->size < sizeof(*fw_info))
2184 goto out;
2185
2186 for (i = 0; i < fw->size; i++)
2187 checksum += fw->data[i];
2188 if (checksum != 0)
2189 goto out;
2190
2191 start = le32_to_cpu(fw_info->fw_start);
2192 if (start > fw->size)
2193 goto out;
2194
2195 size = le32_to_cpu(fw_info->fw_len);
2196 if (size > (fw->size - start) / FW_OPCODE_SIZE)
2197 goto out;
2198
2199 memcpy(version, fw_info->version, RTL_VER_SIZE);
2200
2201 pa->code = (__le32 *)(fw->data + start);
2202 pa->size = size;
2203 } else {
Francois Romieu1c361ef2011-06-17 17:16:24 +02002204 if (fw->size % FW_OPCODE_SIZE)
2205 goto out;
2206
2207 strlcpy(version, rtl_lookup_firmware_name(tp), RTL_VER_SIZE);
2208
2209 pa->code = (__le32 *)fw->data;
2210 pa->size = fw->size / FW_OPCODE_SIZE;
2211 }
2212 version[RTL_VER_SIZE - 1] = 0;
2213
2214 rc = true;
2215out:
2216 return rc;
2217}
2218
Francois Romieufd112f22011-06-18 00:10:29 +02002219static bool rtl_fw_data_ok(struct rtl8169_private *tp, struct net_device *dev,
2220 struct rtl_fw_phy_action *pa)
Francois Romieu1c361ef2011-06-17 17:16:24 +02002221{
Francois Romieufd112f22011-06-18 00:10:29 +02002222 bool rc = false;
Francois Romieu1c361ef2011-06-17 17:16:24 +02002223 size_t index;
2224
Francois Romieu1c361ef2011-06-17 17:16:24 +02002225 for (index = 0; index < pa->size; index++) {
2226 u32 action = le32_to_cpu(pa->code[index]);
hayeswang42b82dc2011-01-10 02:07:25 +00002227 u32 regno = (action & 0x0fff0000) >> 16;
françois romieubca03d52011-01-03 15:07:31 +00002228
hayeswang42b82dc2011-01-10 02:07:25 +00002229 switch(action & 0xf0000000) {
2230 case PHY_READ:
2231 case PHY_DATA_OR:
2232 case PHY_DATA_AND:
2233 case PHY_READ_EFUSE:
2234 case PHY_CLEAR_READCOUNT:
2235 case PHY_WRITE:
2236 case PHY_WRITE_PREVIOUS:
2237 case PHY_DELAY_MS:
françois romieubca03d52011-01-03 15:07:31 +00002238 break;
2239
hayeswang42b82dc2011-01-10 02:07:25 +00002240 case PHY_BJMPN:
2241 if (regno > index) {
Francois Romieufd112f22011-06-18 00:10:29 +02002242 netif_err(tp, ifup, tp->dev,
Francois Romieucecb5fd2011-04-01 10:21:07 +02002243 "Out of range of firmware\n");
Francois Romieufd112f22011-06-18 00:10:29 +02002244 goto out;
hayeswang42b82dc2011-01-10 02:07:25 +00002245 }
2246 break;
2247 case PHY_READCOUNT_EQ_SKIP:
Francois Romieu1c361ef2011-06-17 17:16:24 +02002248 if (index + 2 >= pa->size) {
Francois Romieufd112f22011-06-18 00:10:29 +02002249 netif_err(tp, ifup, tp->dev,
Francois Romieucecb5fd2011-04-01 10:21:07 +02002250 "Out of range of firmware\n");
Francois Romieufd112f22011-06-18 00:10:29 +02002251 goto out;
hayeswang42b82dc2011-01-10 02:07:25 +00002252 }
2253 break;
2254 case PHY_COMP_EQ_SKIPN:
2255 case PHY_COMP_NEQ_SKIPN:
2256 case PHY_SKIPN:
Francois Romieu1c361ef2011-06-17 17:16:24 +02002257 if (index + 1 + regno >= pa->size) {
Francois Romieufd112f22011-06-18 00:10:29 +02002258 netif_err(tp, ifup, tp->dev,
Francois Romieucecb5fd2011-04-01 10:21:07 +02002259 "Out of range of firmware\n");
Francois Romieufd112f22011-06-18 00:10:29 +02002260 goto out;
hayeswang42b82dc2011-01-10 02:07:25 +00002261 }
2262 break;
2263
2264 case PHY_READ_MAC_BYTE:
2265 case PHY_WRITE_MAC_BYTE:
2266 case PHY_WRITE_ERI_WORD:
2267 default:
Francois Romieufd112f22011-06-18 00:10:29 +02002268 netif_err(tp, ifup, tp->dev,
hayeswang42b82dc2011-01-10 02:07:25 +00002269 "Invalid action 0x%08x\n", action);
Francois Romieufd112f22011-06-18 00:10:29 +02002270 goto out;
françois romieubca03d52011-01-03 15:07:31 +00002271 }
2272 }
Francois Romieufd112f22011-06-18 00:10:29 +02002273 rc = true;
2274out:
2275 return rc;
2276}
françois romieubca03d52011-01-03 15:07:31 +00002277
Francois Romieufd112f22011-06-18 00:10:29 +02002278static int rtl_check_firmware(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
2279{
2280 struct net_device *dev = tp->dev;
2281 int rc = -EINVAL;
2282
2283 if (!rtl_fw_format_ok(tp, rtl_fw)) {
2284 netif_err(tp, ifup, dev, "invalid firwmare\n");
2285 goto out;
2286 }
2287
2288 if (rtl_fw_data_ok(tp, dev, &rtl_fw->phy_action))
2289 rc = 0;
2290out:
2291 return rc;
2292}
2293
2294static void rtl_phy_write_fw(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
2295{
2296 struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
2297 u32 predata, count;
2298 size_t index;
2299
2300 predata = count = 0;
hayeswang42b82dc2011-01-10 02:07:25 +00002301
Francois Romieu1c361ef2011-06-17 17:16:24 +02002302 for (index = 0; index < pa->size; ) {
2303 u32 action = le32_to_cpu(pa->code[index]);
françois romieubca03d52011-01-03 15:07:31 +00002304 u32 data = action & 0x0000ffff;
hayeswang42b82dc2011-01-10 02:07:25 +00002305 u32 regno = (action & 0x0fff0000) >> 16;
2306
2307 if (!action)
2308 break;
françois romieubca03d52011-01-03 15:07:31 +00002309
2310 switch(action & 0xf0000000) {
hayeswang42b82dc2011-01-10 02:07:25 +00002311 case PHY_READ:
2312 predata = rtl_readphy(tp, regno);
2313 count++;
2314 index++;
françois romieubca03d52011-01-03 15:07:31 +00002315 break;
hayeswang42b82dc2011-01-10 02:07:25 +00002316 case PHY_DATA_OR:
2317 predata |= data;
2318 index++;
2319 break;
2320 case PHY_DATA_AND:
2321 predata &= data;
2322 index++;
2323 break;
2324 case PHY_BJMPN:
2325 index -= regno;
2326 break;
2327 case PHY_READ_EFUSE:
Francois Romieufdf6fc02012-07-06 22:40:38 +02002328 predata = rtl8168d_efuse_read(tp, regno);
hayeswang42b82dc2011-01-10 02:07:25 +00002329 index++;
2330 break;
2331 case PHY_CLEAR_READCOUNT:
2332 count = 0;
2333 index++;
2334 break;
2335 case PHY_WRITE:
2336 rtl_writephy(tp, regno, data);
2337 index++;
2338 break;
2339 case PHY_READCOUNT_EQ_SKIP:
Francois Romieucecb5fd2011-04-01 10:21:07 +02002340 index += (count == data) ? 2 : 1;
hayeswang42b82dc2011-01-10 02:07:25 +00002341 break;
2342 case PHY_COMP_EQ_SKIPN:
2343 if (predata == data)
2344 index += regno;
2345 index++;
2346 break;
2347 case PHY_COMP_NEQ_SKIPN:
2348 if (predata != data)
2349 index += regno;
2350 index++;
2351 break;
2352 case PHY_WRITE_PREVIOUS:
2353 rtl_writephy(tp, regno, predata);
2354 index++;
2355 break;
2356 case PHY_SKIPN:
2357 index += regno + 1;
2358 break;
2359 case PHY_DELAY_MS:
2360 mdelay(data);
2361 index++;
2362 break;
2363
2364 case PHY_READ_MAC_BYTE:
2365 case PHY_WRITE_MAC_BYTE:
2366 case PHY_WRITE_ERI_WORD:
françois romieubca03d52011-01-03 15:07:31 +00002367 default:
2368 BUG();
2369 }
2370 }
2371}
2372
françois romieuf1e02ed2011-01-13 13:07:53 +00002373static void rtl_release_firmware(struct rtl8169_private *tp)
2374{
Francois Romieub6ffd972011-06-17 17:00:05 +02002375 if (!IS_ERR_OR_NULL(tp->rtl_fw)) {
2376 release_firmware(tp->rtl_fw->fw);
2377 kfree(tp->rtl_fw);
2378 }
2379 tp->rtl_fw = RTL_FIRMWARE_UNKNOWN;
françois romieuf1e02ed2011-01-13 13:07:53 +00002380}
2381
François Romieu953a12c2011-04-24 17:38:48 +02002382static void rtl_apply_firmware(struct rtl8169_private *tp)
françois romieuf1e02ed2011-01-13 13:07:53 +00002383{
Francois Romieub6ffd972011-06-17 17:00:05 +02002384 struct rtl_fw *rtl_fw = tp->rtl_fw;
françois romieuf1e02ed2011-01-13 13:07:53 +00002385
2386 /* TODO: release firmware once rtl_phy_write_fw signals failures. */
Francois Romieueef63cc2013-02-08 23:43:20 +01002387 if (!IS_ERR_OR_NULL(rtl_fw))
Francois Romieub6ffd972011-06-17 17:00:05 +02002388 rtl_phy_write_fw(tp, rtl_fw);
François Romieu953a12c2011-04-24 17:38:48 +02002389}
2390
2391static void rtl_apply_firmware_cond(struct rtl8169_private *tp, u8 reg, u16 val)
2392{
2393 if (rtl_readphy(tp, reg) != val)
2394 netif_warn(tp, hw, tp->dev, "chipset not ready for firmware\n");
2395 else
2396 rtl_apply_firmware(tp);
françois romieuf1e02ed2011-01-13 13:07:53 +00002397}
2398
françois romieu4da19632011-01-03 15:07:55 +00002399static void rtl8169s_hw_phy_config(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002400{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002401 static const struct phy_reg phy_reg_init[] = {
françois romieu0b9b5712009-08-10 19:44:56 +00002402 { 0x1f, 0x0001 },
2403 { 0x06, 0x006e },
2404 { 0x08, 0x0708 },
2405 { 0x15, 0x4000 },
2406 { 0x18, 0x65c7 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07002407
françois romieu0b9b5712009-08-10 19:44:56 +00002408 { 0x1f, 0x0001 },
2409 { 0x03, 0x00a1 },
2410 { 0x02, 0x0008 },
2411 { 0x01, 0x0120 },
2412 { 0x00, 0x1000 },
2413 { 0x04, 0x0800 },
2414 { 0x04, 0x0000 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07002415
françois romieu0b9b5712009-08-10 19:44:56 +00002416 { 0x03, 0xff41 },
2417 { 0x02, 0xdf60 },
2418 { 0x01, 0x0140 },
2419 { 0x00, 0x0077 },
2420 { 0x04, 0x7800 },
2421 { 0x04, 0x7000 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07002422
françois romieu0b9b5712009-08-10 19:44:56 +00002423 { 0x03, 0x802f },
2424 { 0x02, 0x4f02 },
2425 { 0x01, 0x0409 },
2426 { 0x00, 0xf0f9 },
2427 { 0x04, 0x9800 },
2428 { 0x04, 0x9000 },
2429
2430 { 0x03, 0xdf01 },
2431 { 0x02, 0xdf20 },
2432 { 0x01, 0xff95 },
2433 { 0x00, 0xba00 },
2434 { 0x04, 0xa800 },
2435 { 0x04, 0xa000 },
2436
2437 { 0x03, 0xff41 },
2438 { 0x02, 0xdf20 },
2439 { 0x01, 0x0140 },
2440 { 0x00, 0x00bb },
2441 { 0x04, 0xb800 },
2442 { 0x04, 0xb000 },
2443
2444 { 0x03, 0xdf41 },
2445 { 0x02, 0xdc60 },
2446 { 0x01, 0x6340 },
2447 { 0x00, 0x007d },
2448 { 0x04, 0xd800 },
2449 { 0x04, 0xd000 },
2450
2451 { 0x03, 0xdf01 },
2452 { 0x02, 0xdf20 },
2453 { 0x01, 0x100a },
2454 { 0x00, 0xa0ff },
2455 { 0x04, 0xf800 },
2456 { 0x04, 0xf000 },
2457
2458 { 0x1f, 0x0000 },
2459 { 0x0b, 0x0000 },
2460 { 0x00, 0x9200 }
2461 };
2462
françois romieu4da19632011-01-03 15:07:55 +00002463 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002464}
2465
françois romieu4da19632011-01-03 15:07:55 +00002466static void rtl8169sb_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu5615d9f2007-08-17 17:50:46 +02002467{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002468 static const struct phy_reg phy_reg_init[] = {
Francois Romieua441d7b2007-08-17 18:26:35 +02002469 { 0x1f, 0x0002 },
2470 { 0x01, 0x90d0 },
2471 { 0x1f, 0x0000 }
2472 };
2473
françois romieu4da19632011-01-03 15:07:55 +00002474 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu5615d9f2007-08-17 17:50:46 +02002475}
2476
françois romieu4da19632011-01-03 15:07:55 +00002477static void rtl8169scd_hw_phy_config_quirk(struct rtl8169_private *tp)
françois romieu2e9558562009-08-10 19:44:19 +00002478{
2479 struct pci_dev *pdev = tp->pci_dev;
françois romieu2e9558562009-08-10 19:44:19 +00002480
Sergei Shtylyovccbae552011-07-22 05:37:24 +00002481 if ((pdev->subsystem_vendor != PCI_VENDOR_ID_GIGABYTE) ||
2482 (pdev->subsystem_device != 0xe000))
françois romieu2e9558562009-08-10 19:44:19 +00002483 return;
2484
françois romieu4da19632011-01-03 15:07:55 +00002485 rtl_writephy(tp, 0x1f, 0x0001);
2486 rtl_writephy(tp, 0x10, 0xf01b);
2487 rtl_writephy(tp, 0x1f, 0x0000);
françois romieu2e9558562009-08-10 19:44:19 +00002488}
2489
françois romieu4da19632011-01-03 15:07:55 +00002490static void rtl8169scd_hw_phy_config(struct rtl8169_private *tp)
françois romieu2e9558562009-08-10 19:44:19 +00002491{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002492 static const struct phy_reg phy_reg_init[] = {
françois romieu2e9558562009-08-10 19:44:19 +00002493 { 0x1f, 0x0001 },
2494 { 0x04, 0x0000 },
2495 { 0x03, 0x00a1 },
2496 { 0x02, 0x0008 },
2497 { 0x01, 0x0120 },
2498 { 0x00, 0x1000 },
2499 { 0x04, 0x0800 },
2500 { 0x04, 0x9000 },
2501 { 0x03, 0x802f },
2502 { 0x02, 0x4f02 },
2503 { 0x01, 0x0409 },
2504 { 0x00, 0xf099 },
2505 { 0x04, 0x9800 },
2506 { 0x04, 0xa000 },
2507 { 0x03, 0xdf01 },
2508 { 0x02, 0xdf20 },
2509 { 0x01, 0xff95 },
2510 { 0x00, 0xba00 },
2511 { 0x04, 0xa800 },
2512 { 0x04, 0xf000 },
2513 { 0x03, 0xdf01 },
2514 { 0x02, 0xdf20 },
2515 { 0x01, 0x101a },
2516 { 0x00, 0xa0ff },
2517 { 0x04, 0xf800 },
2518 { 0x04, 0x0000 },
2519 { 0x1f, 0x0000 },
2520
2521 { 0x1f, 0x0001 },
2522 { 0x10, 0xf41b },
2523 { 0x14, 0xfb54 },
2524 { 0x18, 0xf5c7 },
2525 { 0x1f, 0x0000 },
2526
2527 { 0x1f, 0x0001 },
2528 { 0x17, 0x0cc0 },
2529 { 0x1f, 0x0000 }
2530 };
2531
françois romieu4da19632011-01-03 15:07:55 +00002532 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieu2e9558562009-08-10 19:44:19 +00002533
françois romieu4da19632011-01-03 15:07:55 +00002534 rtl8169scd_hw_phy_config_quirk(tp);
françois romieu2e9558562009-08-10 19:44:19 +00002535}
2536
françois romieu4da19632011-01-03 15:07:55 +00002537static void rtl8169sce_hw_phy_config(struct rtl8169_private *tp)
françois romieu8c7006a2009-08-10 19:43:29 +00002538{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002539 static const struct phy_reg phy_reg_init[] = {
françois romieu8c7006a2009-08-10 19:43:29 +00002540 { 0x1f, 0x0001 },
2541 { 0x04, 0x0000 },
2542 { 0x03, 0x00a1 },
2543 { 0x02, 0x0008 },
2544 { 0x01, 0x0120 },
2545 { 0x00, 0x1000 },
2546 { 0x04, 0x0800 },
2547 { 0x04, 0x9000 },
2548 { 0x03, 0x802f },
2549 { 0x02, 0x4f02 },
2550 { 0x01, 0x0409 },
2551 { 0x00, 0xf099 },
2552 { 0x04, 0x9800 },
2553 { 0x04, 0xa000 },
2554 { 0x03, 0xdf01 },
2555 { 0x02, 0xdf20 },
2556 { 0x01, 0xff95 },
2557 { 0x00, 0xba00 },
2558 { 0x04, 0xa800 },
2559 { 0x04, 0xf000 },
2560 { 0x03, 0xdf01 },
2561 { 0x02, 0xdf20 },
2562 { 0x01, 0x101a },
2563 { 0x00, 0xa0ff },
2564 { 0x04, 0xf800 },
2565 { 0x04, 0x0000 },
2566 { 0x1f, 0x0000 },
2567
2568 { 0x1f, 0x0001 },
2569 { 0x0b, 0x8480 },
2570 { 0x1f, 0x0000 },
2571
2572 { 0x1f, 0x0001 },
2573 { 0x18, 0x67c7 },
2574 { 0x04, 0x2000 },
2575 { 0x03, 0x002f },
2576 { 0x02, 0x4360 },
2577 { 0x01, 0x0109 },
2578 { 0x00, 0x3022 },
2579 { 0x04, 0x2800 },
2580 { 0x1f, 0x0000 },
2581
2582 { 0x1f, 0x0001 },
2583 { 0x17, 0x0cc0 },
2584 { 0x1f, 0x0000 }
2585 };
2586
françois romieu4da19632011-01-03 15:07:55 +00002587 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieu8c7006a2009-08-10 19:43:29 +00002588}
2589
françois romieu4da19632011-01-03 15:07:55 +00002590static void rtl8168bb_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu236b8082008-05-30 16:11:48 +02002591{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002592 static const struct phy_reg phy_reg_init[] = {
Francois Romieu236b8082008-05-30 16:11:48 +02002593 { 0x10, 0xf41b },
2594 { 0x1f, 0x0000 }
2595 };
2596
françois romieu4da19632011-01-03 15:07:55 +00002597 rtl_writephy(tp, 0x1f, 0x0001);
2598 rtl_patchphy(tp, 0x16, 1 << 0);
Francois Romieu236b8082008-05-30 16:11:48 +02002599
françois romieu4da19632011-01-03 15:07:55 +00002600 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu236b8082008-05-30 16:11:48 +02002601}
2602
françois romieu4da19632011-01-03 15:07:55 +00002603static void rtl8168bef_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu236b8082008-05-30 16:11:48 +02002604{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002605 static const struct phy_reg phy_reg_init[] = {
Francois Romieu236b8082008-05-30 16:11:48 +02002606 { 0x1f, 0x0001 },
2607 { 0x10, 0xf41b },
2608 { 0x1f, 0x0000 }
2609 };
2610
françois romieu4da19632011-01-03 15:07:55 +00002611 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu236b8082008-05-30 16:11:48 +02002612}
2613
françois romieu4da19632011-01-03 15:07:55 +00002614static void rtl8168cp_1_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu867763c2007-08-17 18:21:58 +02002615{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002616 static const struct phy_reg phy_reg_init[] = {
Francois Romieu867763c2007-08-17 18:21:58 +02002617 { 0x1f, 0x0000 },
2618 { 0x1d, 0x0f00 },
2619 { 0x1f, 0x0002 },
2620 { 0x0c, 0x1ec8 },
2621 { 0x1f, 0x0000 }
2622 };
2623
françois romieu4da19632011-01-03 15:07:55 +00002624 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu867763c2007-08-17 18:21:58 +02002625}
2626
françois romieu4da19632011-01-03 15:07:55 +00002627static void rtl8168cp_2_hw_phy_config(struct rtl8169_private *tp)
Francois Romieuef3386f2008-06-29 12:24:30 +02002628{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002629 static const struct phy_reg phy_reg_init[] = {
Francois Romieuef3386f2008-06-29 12:24:30 +02002630 { 0x1f, 0x0001 },
2631 { 0x1d, 0x3d98 },
2632 { 0x1f, 0x0000 }
2633 };
2634
françois romieu4da19632011-01-03 15:07:55 +00002635 rtl_writephy(tp, 0x1f, 0x0000);
2636 rtl_patchphy(tp, 0x14, 1 << 5);
2637 rtl_patchphy(tp, 0x0d, 1 << 5);
Francois Romieuef3386f2008-06-29 12:24:30 +02002638
françois romieu4da19632011-01-03 15:07:55 +00002639 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieuef3386f2008-06-29 12:24:30 +02002640}
2641
françois romieu4da19632011-01-03 15:07:55 +00002642static void rtl8168c_1_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu867763c2007-08-17 18:21:58 +02002643{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002644 static const struct phy_reg phy_reg_init[] = {
Francois Romieua3f80672007-10-18 14:35:11 +02002645 { 0x1f, 0x0001 },
2646 { 0x12, 0x2300 },
Francois Romieu867763c2007-08-17 18:21:58 +02002647 { 0x1f, 0x0002 },
2648 { 0x00, 0x88d4 },
2649 { 0x01, 0x82b1 },
2650 { 0x03, 0x7002 },
2651 { 0x08, 0x9e30 },
2652 { 0x09, 0x01f0 },
2653 { 0x0a, 0x5500 },
2654 { 0x0c, 0x00c8 },
2655 { 0x1f, 0x0003 },
2656 { 0x12, 0xc096 },
2657 { 0x16, 0x000a },
Francois Romieuf50d4272008-05-30 16:07:07 +02002658 { 0x1f, 0x0000 },
2659 { 0x1f, 0x0000 },
2660 { 0x09, 0x2000 },
2661 { 0x09, 0x0000 }
Francois Romieu867763c2007-08-17 18:21:58 +02002662 };
2663
françois romieu4da19632011-01-03 15:07:55 +00002664 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieuf50d4272008-05-30 16:07:07 +02002665
françois romieu4da19632011-01-03 15:07:55 +00002666 rtl_patchphy(tp, 0x14, 1 << 5);
2667 rtl_patchphy(tp, 0x0d, 1 << 5);
2668 rtl_writephy(tp, 0x1f, 0x0000);
Francois Romieu867763c2007-08-17 18:21:58 +02002669}
2670
françois romieu4da19632011-01-03 15:07:55 +00002671static void rtl8168c_2_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu7da97ec2007-10-18 15:20:43 +02002672{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002673 static const struct phy_reg phy_reg_init[] = {
Francois Romieuf50d4272008-05-30 16:07:07 +02002674 { 0x1f, 0x0001 },
Francois Romieu7da97ec2007-10-18 15:20:43 +02002675 { 0x12, 0x2300 },
Francois Romieuf50d4272008-05-30 16:07:07 +02002676 { 0x03, 0x802f },
2677 { 0x02, 0x4f02 },
2678 { 0x01, 0x0409 },
2679 { 0x00, 0xf099 },
2680 { 0x04, 0x9800 },
2681 { 0x04, 0x9000 },
2682 { 0x1d, 0x3d98 },
Francois Romieu7da97ec2007-10-18 15:20:43 +02002683 { 0x1f, 0x0002 },
2684 { 0x0c, 0x7eb8 },
Francois Romieuf50d4272008-05-30 16:07:07 +02002685 { 0x06, 0x0761 },
2686 { 0x1f, 0x0003 },
2687 { 0x16, 0x0f0a },
Francois Romieu7da97ec2007-10-18 15:20:43 +02002688 { 0x1f, 0x0000 }
2689 };
2690
françois romieu4da19632011-01-03 15:07:55 +00002691 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieuf50d4272008-05-30 16:07:07 +02002692
françois romieu4da19632011-01-03 15:07:55 +00002693 rtl_patchphy(tp, 0x16, 1 << 0);
2694 rtl_patchphy(tp, 0x14, 1 << 5);
2695 rtl_patchphy(tp, 0x0d, 1 << 5);
2696 rtl_writephy(tp, 0x1f, 0x0000);
Francois Romieu7da97ec2007-10-18 15:20:43 +02002697}
2698
françois romieu4da19632011-01-03 15:07:55 +00002699static void rtl8168c_3_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu197ff762008-06-28 13:16:02 +02002700{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002701 static const struct phy_reg phy_reg_init[] = {
Francois Romieu197ff762008-06-28 13:16:02 +02002702 { 0x1f, 0x0001 },
2703 { 0x12, 0x2300 },
2704 { 0x1d, 0x3d98 },
2705 { 0x1f, 0x0002 },
2706 { 0x0c, 0x7eb8 },
2707 { 0x06, 0x5461 },
2708 { 0x1f, 0x0003 },
2709 { 0x16, 0x0f0a },
2710 { 0x1f, 0x0000 }
2711 };
2712
françois romieu4da19632011-01-03 15:07:55 +00002713 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu197ff762008-06-28 13:16:02 +02002714
françois romieu4da19632011-01-03 15:07:55 +00002715 rtl_patchphy(tp, 0x16, 1 << 0);
2716 rtl_patchphy(tp, 0x14, 1 << 5);
2717 rtl_patchphy(tp, 0x0d, 1 << 5);
2718 rtl_writephy(tp, 0x1f, 0x0000);
Francois Romieu197ff762008-06-28 13:16:02 +02002719}
2720
françois romieu4da19632011-01-03 15:07:55 +00002721static void rtl8168c_4_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu6fb07052008-06-29 11:54:28 +02002722{
françois romieu4da19632011-01-03 15:07:55 +00002723 rtl8168c_3_hw_phy_config(tp);
Francois Romieu6fb07052008-06-29 11:54:28 +02002724}
2725
françois romieubca03d52011-01-03 15:07:31 +00002726static void rtl8168d_1_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu5b538df2008-07-20 16:22:45 +02002727{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002728 static const struct phy_reg phy_reg_init_0[] = {
françois romieubca03d52011-01-03 15:07:31 +00002729 /* Channel Estimation */
Francois Romieu5b538df2008-07-20 16:22:45 +02002730 { 0x1f, 0x0001 },
françois romieudaf9df62009-10-07 12:44:20 +00002731 { 0x06, 0x4064 },
2732 { 0x07, 0x2863 },
2733 { 0x08, 0x059c },
2734 { 0x09, 0x26b4 },
2735 { 0x0a, 0x6a19 },
2736 { 0x0b, 0xdcc8 },
2737 { 0x10, 0xf06d },
2738 { 0x14, 0x7f68 },
2739 { 0x18, 0x7fd9 },
2740 { 0x1c, 0xf0ff },
2741 { 0x1d, 0x3d9c },
Francois Romieu5b538df2008-07-20 16:22:45 +02002742 { 0x1f, 0x0003 },
françois romieudaf9df62009-10-07 12:44:20 +00002743 { 0x12, 0xf49f },
2744 { 0x13, 0x070b },
2745 { 0x1a, 0x05ad },
françois romieubca03d52011-01-03 15:07:31 +00002746 { 0x14, 0x94c0 },
2747
2748 /*
2749 * Tx Error Issue
Francois Romieucecb5fd2011-04-01 10:21:07 +02002750 * Enhance line driver power
françois romieubca03d52011-01-03 15:07:31 +00002751 */
Francois Romieu5b538df2008-07-20 16:22:45 +02002752 { 0x1f, 0x0002 },
françois romieudaf9df62009-10-07 12:44:20 +00002753 { 0x06, 0x5561 },
Francois Romieu5b538df2008-07-20 16:22:45 +02002754 { 0x1f, 0x0005 },
françois romieudaf9df62009-10-07 12:44:20 +00002755 { 0x05, 0x8332 },
françois romieubca03d52011-01-03 15:07:31 +00002756 { 0x06, 0x5561 },
2757
2758 /*
2759 * Can not link to 1Gbps with bad cable
2760 * Decrease SNR threshold form 21.07dB to 19.04dB
2761 */
2762 { 0x1f, 0x0001 },
2763 { 0x17, 0x0cc0 },
françois romieudaf9df62009-10-07 12:44:20 +00002764
2765 { 0x1f, 0x0000 },
françois romieubca03d52011-01-03 15:07:31 +00002766 { 0x0d, 0xf880 }
Francois Romieu5b538df2008-07-20 16:22:45 +02002767 };
2768
françois romieu4da19632011-01-03 15:07:55 +00002769 rtl_writephy_batch(tp, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0));
Francois Romieu5b538df2008-07-20 16:22:45 +02002770
françois romieubca03d52011-01-03 15:07:31 +00002771 /*
2772 * Rx Error Issue
2773 * Fine Tune Switching regulator parameter
2774 */
françois romieu4da19632011-01-03 15:07:55 +00002775 rtl_writephy(tp, 0x1f, 0x0002);
2776 rtl_w1w0_phy(tp, 0x0b, 0x0010, 0x00ef);
2777 rtl_w1w0_phy(tp, 0x0c, 0xa200, 0x5d00);
françois romieudaf9df62009-10-07 12:44:20 +00002778
Francois Romieufdf6fc02012-07-06 22:40:38 +02002779 if (rtl8168d_efuse_read(tp, 0x01) == 0xb1) {
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002780 static const struct phy_reg phy_reg_init[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002781 { 0x1f, 0x0002 },
2782 { 0x05, 0x669a },
Francois Romieu5b538df2008-07-20 16:22:45 +02002783 { 0x1f, 0x0005 },
françois romieudaf9df62009-10-07 12:44:20 +00002784 { 0x05, 0x8330 },
2785 { 0x06, 0x669a },
2786 { 0x1f, 0x0002 }
2787 };
2788 int val;
2789
françois romieu4da19632011-01-03 15:07:55 +00002790 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieudaf9df62009-10-07 12:44:20 +00002791
françois romieu4da19632011-01-03 15:07:55 +00002792 val = rtl_readphy(tp, 0x0d);
françois romieudaf9df62009-10-07 12:44:20 +00002793
2794 if ((val & 0x00ff) != 0x006c) {
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002795 static const u32 set[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002796 0x0065, 0x0066, 0x0067, 0x0068,
2797 0x0069, 0x006a, 0x006b, 0x006c
2798 };
2799 int i;
2800
françois romieu4da19632011-01-03 15:07:55 +00002801 rtl_writephy(tp, 0x1f, 0x0002);
françois romieudaf9df62009-10-07 12:44:20 +00002802
2803 val &= 0xff00;
2804 for (i = 0; i < ARRAY_SIZE(set); i++)
françois romieu4da19632011-01-03 15:07:55 +00002805 rtl_writephy(tp, 0x0d, val | set[i]);
françois romieudaf9df62009-10-07 12:44:20 +00002806 }
2807 } else {
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002808 static const struct phy_reg phy_reg_init[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002809 { 0x1f, 0x0002 },
2810 { 0x05, 0x6662 },
Francois Romieu5b538df2008-07-20 16:22:45 +02002811 { 0x1f, 0x0005 },
françois romieudaf9df62009-10-07 12:44:20 +00002812 { 0x05, 0x8330 },
2813 { 0x06, 0x6662 }
Francois Romieu5b538df2008-07-20 16:22:45 +02002814 };
2815
françois romieu4da19632011-01-03 15:07:55 +00002816 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu5b538df2008-07-20 16:22:45 +02002817 }
2818
françois romieubca03d52011-01-03 15:07:31 +00002819 /* RSET couple improve */
françois romieu4da19632011-01-03 15:07:55 +00002820 rtl_writephy(tp, 0x1f, 0x0002);
2821 rtl_patchphy(tp, 0x0d, 0x0300);
2822 rtl_patchphy(tp, 0x0f, 0x0010);
françois romieudaf9df62009-10-07 12:44:20 +00002823
françois romieubca03d52011-01-03 15:07:31 +00002824 /* Fine tune PLL performance */
françois romieu4da19632011-01-03 15:07:55 +00002825 rtl_writephy(tp, 0x1f, 0x0002);
2826 rtl_w1w0_phy(tp, 0x02, 0x0100, 0x0600);
2827 rtl_w1w0_phy(tp, 0x03, 0x0000, 0xe000);
françois romieudaf9df62009-10-07 12:44:20 +00002828
françois romieu4da19632011-01-03 15:07:55 +00002829 rtl_writephy(tp, 0x1f, 0x0005);
2830 rtl_writephy(tp, 0x05, 0x001b);
François Romieu953a12c2011-04-24 17:38:48 +02002831
2832 rtl_apply_firmware_cond(tp, MII_EXPANSION, 0xbf00);
françois romieubca03d52011-01-03 15:07:31 +00002833
françois romieu4da19632011-01-03 15:07:55 +00002834 rtl_writephy(tp, 0x1f, 0x0000);
françois romieudaf9df62009-10-07 12:44:20 +00002835}
2836
françois romieubca03d52011-01-03 15:07:31 +00002837static void rtl8168d_2_hw_phy_config(struct rtl8169_private *tp)
françois romieudaf9df62009-10-07 12:44:20 +00002838{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002839 static const struct phy_reg phy_reg_init_0[] = {
françois romieubca03d52011-01-03 15:07:31 +00002840 /* Channel Estimation */
françois romieudaf9df62009-10-07 12:44:20 +00002841 { 0x1f, 0x0001 },
2842 { 0x06, 0x4064 },
2843 { 0x07, 0x2863 },
2844 { 0x08, 0x059c },
2845 { 0x09, 0x26b4 },
2846 { 0x0a, 0x6a19 },
2847 { 0x0b, 0xdcc8 },
2848 { 0x10, 0xf06d },
2849 { 0x14, 0x7f68 },
2850 { 0x18, 0x7fd9 },
2851 { 0x1c, 0xf0ff },
2852 { 0x1d, 0x3d9c },
2853 { 0x1f, 0x0003 },
2854 { 0x12, 0xf49f },
2855 { 0x13, 0x070b },
2856 { 0x1a, 0x05ad },
2857 { 0x14, 0x94c0 },
2858
françois romieubca03d52011-01-03 15:07:31 +00002859 /*
2860 * Tx Error Issue
Francois Romieucecb5fd2011-04-01 10:21:07 +02002861 * Enhance line driver power
françois romieubca03d52011-01-03 15:07:31 +00002862 */
françois romieudaf9df62009-10-07 12:44:20 +00002863 { 0x1f, 0x0002 },
2864 { 0x06, 0x5561 },
2865 { 0x1f, 0x0005 },
2866 { 0x05, 0x8332 },
françois romieubca03d52011-01-03 15:07:31 +00002867 { 0x06, 0x5561 },
2868
2869 /*
2870 * Can not link to 1Gbps with bad cable
2871 * Decrease SNR threshold form 21.07dB to 19.04dB
2872 */
2873 { 0x1f, 0x0001 },
2874 { 0x17, 0x0cc0 },
françois romieudaf9df62009-10-07 12:44:20 +00002875
2876 { 0x1f, 0x0000 },
françois romieubca03d52011-01-03 15:07:31 +00002877 { 0x0d, 0xf880 }
françois romieudaf9df62009-10-07 12:44:20 +00002878 };
2879
françois romieu4da19632011-01-03 15:07:55 +00002880 rtl_writephy_batch(tp, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0));
françois romieudaf9df62009-10-07 12:44:20 +00002881
Francois Romieufdf6fc02012-07-06 22:40:38 +02002882 if (rtl8168d_efuse_read(tp, 0x01) == 0xb1) {
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002883 static const struct phy_reg phy_reg_init[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002884 { 0x1f, 0x0002 },
2885 { 0x05, 0x669a },
2886 { 0x1f, 0x0005 },
2887 { 0x05, 0x8330 },
2888 { 0x06, 0x669a },
2889
2890 { 0x1f, 0x0002 }
2891 };
2892 int val;
2893
françois romieu4da19632011-01-03 15:07:55 +00002894 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieudaf9df62009-10-07 12:44:20 +00002895
françois romieu4da19632011-01-03 15:07:55 +00002896 val = rtl_readphy(tp, 0x0d);
françois romieudaf9df62009-10-07 12:44:20 +00002897 if ((val & 0x00ff) != 0x006c) {
Joe Perchesb6bc7652010-12-21 02:16:08 -08002898 static const u32 set[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002899 0x0065, 0x0066, 0x0067, 0x0068,
2900 0x0069, 0x006a, 0x006b, 0x006c
2901 };
2902 int i;
2903
françois romieu4da19632011-01-03 15:07:55 +00002904 rtl_writephy(tp, 0x1f, 0x0002);
françois romieudaf9df62009-10-07 12:44:20 +00002905
2906 val &= 0xff00;
2907 for (i = 0; i < ARRAY_SIZE(set); i++)
françois romieu4da19632011-01-03 15:07:55 +00002908 rtl_writephy(tp, 0x0d, val | set[i]);
françois romieudaf9df62009-10-07 12:44:20 +00002909 }
2910 } else {
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002911 static const struct phy_reg phy_reg_init[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002912 { 0x1f, 0x0002 },
2913 { 0x05, 0x2642 },
2914 { 0x1f, 0x0005 },
2915 { 0x05, 0x8330 },
2916 { 0x06, 0x2642 }
2917 };
2918
françois romieu4da19632011-01-03 15:07:55 +00002919 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieudaf9df62009-10-07 12:44:20 +00002920 }
2921
françois romieubca03d52011-01-03 15:07:31 +00002922 /* Fine tune PLL performance */
françois romieu4da19632011-01-03 15:07:55 +00002923 rtl_writephy(tp, 0x1f, 0x0002);
2924 rtl_w1w0_phy(tp, 0x02, 0x0100, 0x0600);
2925 rtl_w1w0_phy(tp, 0x03, 0x0000, 0xe000);
françois romieudaf9df62009-10-07 12:44:20 +00002926
françois romieubca03d52011-01-03 15:07:31 +00002927 /* Switching regulator Slew rate */
françois romieu4da19632011-01-03 15:07:55 +00002928 rtl_writephy(tp, 0x1f, 0x0002);
2929 rtl_patchphy(tp, 0x0f, 0x0017);
françois romieudaf9df62009-10-07 12:44:20 +00002930
françois romieu4da19632011-01-03 15:07:55 +00002931 rtl_writephy(tp, 0x1f, 0x0005);
2932 rtl_writephy(tp, 0x05, 0x001b);
François Romieu953a12c2011-04-24 17:38:48 +02002933
2934 rtl_apply_firmware_cond(tp, MII_EXPANSION, 0xb300);
françois romieubca03d52011-01-03 15:07:31 +00002935
françois romieu4da19632011-01-03 15:07:55 +00002936 rtl_writephy(tp, 0x1f, 0x0000);
françois romieudaf9df62009-10-07 12:44:20 +00002937}
2938
françois romieu4da19632011-01-03 15:07:55 +00002939static void rtl8168d_3_hw_phy_config(struct rtl8169_private *tp)
françois romieudaf9df62009-10-07 12:44:20 +00002940{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002941 static const struct phy_reg phy_reg_init[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002942 { 0x1f, 0x0002 },
2943 { 0x10, 0x0008 },
2944 { 0x0d, 0x006c },
2945
2946 { 0x1f, 0x0000 },
2947 { 0x0d, 0xf880 },
2948
2949 { 0x1f, 0x0001 },
2950 { 0x17, 0x0cc0 },
2951
2952 { 0x1f, 0x0001 },
2953 { 0x0b, 0xa4d8 },
2954 { 0x09, 0x281c },
2955 { 0x07, 0x2883 },
2956 { 0x0a, 0x6b35 },
2957 { 0x1d, 0x3da4 },
2958 { 0x1c, 0xeffd },
2959 { 0x14, 0x7f52 },
2960 { 0x18, 0x7fc6 },
2961 { 0x08, 0x0601 },
2962 { 0x06, 0x4063 },
2963 { 0x10, 0xf074 },
2964 { 0x1f, 0x0003 },
2965 { 0x13, 0x0789 },
2966 { 0x12, 0xf4bd },
2967 { 0x1a, 0x04fd },
2968 { 0x14, 0x84b0 },
2969 { 0x1f, 0x0000 },
2970 { 0x00, 0x9200 },
2971
2972 { 0x1f, 0x0005 },
2973 { 0x01, 0x0340 },
2974 { 0x1f, 0x0001 },
2975 { 0x04, 0x4000 },
2976 { 0x03, 0x1d21 },
2977 { 0x02, 0x0c32 },
2978 { 0x01, 0x0200 },
2979 { 0x00, 0x5554 },
2980 { 0x04, 0x4800 },
2981 { 0x04, 0x4000 },
2982 { 0x04, 0xf000 },
2983 { 0x03, 0xdf01 },
2984 { 0x02, 0xdf20 },
2985 { 0x01, 0x101a },
2986 { 0x00, 0xa0ff },
2987 { 0x04, 0xf800 },
2988 { 0x04, 0xf000 },
2989 { 0x1f, 0x0000 },
2990
2991 { 0x1f, 0x0007 },
2992 { 0x1e, 0x0023 },
2993 { 0x16, 0x0000 },
2994 { 0x1f, 0x0000 }
2995 };
2996
françois romieu4da19632011-01-03 15:07:55 +00002997 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu5b538df2008-07-20 16:22:45 +02002998}
2999
françois romieue6de30d2011-01-03 15:08:37 +00003000static void rtl8168d_4_hw_phy_config(struct rtl8169_private *tp)
3001{
3002 static const struct phy_reg phy_reg_init[] = {
3003 { 0x1f, 0x0001 },
3004 { 0x17, 0x0cc0 },
3005
3006 { 0x1f, 0x0007 },
3007 { 0x1e, 0x002d },
3008 { 0x18, 0x0040 },
3009 { 0x1f, 0x0000 }
3010 };
3011
3012 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3013 rtl_patchphy(tp, 0x0d, 1 << 5);
3014}
3015
Hayes Wang70090422011-07-06 15:58:06 +08003016static void rtl8168e_1_hw_phy_config(struct rtl8169_private *tp)
hayeswang01dc7fe2011-03-21 01:50:28 +00003017{
3018 static const struct phy_reg phy_reg_init[] = {
3019 /* Enable Delay cap */
3020 { 0x1f, 0x0005 },
3021 { 0x05, 0x8b80 },
3022 { 0x06, 0xc896 },
3023 { 0x1f, 0x0000 },
3024
3025 /* Channel estimation fine tune */
3026 { 0x1f, 0x0001 },
3027 { 0x0b, 0x6c20 },
3028 { 0x07, 0x2872 },
3029 { 0x1c, 0xefff },
3030 { 0x1f, 0x0003 },
3031 { 0x14, 0x6420 },
3032 { 0x1f, 0x0000 },
3033
3034 /* Update PFM & 10M TX idle timer */
3035 { 0x1f, 0x0007 },
3036 { 0x1e, 0x002f },
3037 { 0x15, 0x1919 },
3038 { 0x1f, 0x0000 },
3039
3040 { 0x1f, 0x0007 },
3041 { 0x1e, 0x00ac },
3042 { 0x18, 0x0006 },
3043 { 0x1f, 0x0000 }
3044 };
3045
Francois Romieu15ecd032011-04-27 13:52:22 -07003046 rtl_apply_firmware(tp);
3047
hayeswang01dc7fe2011-03-21 01:50:28 +00003048 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3049
3050 /* DCO enable for 10M IDLE Power */
3051 rtl_writephy(tp, 0x1f, 0x0007);
3052 rtl_writephy(tp, 0x1e, 0x0023);
3053 rtl_w1w0_phy(tp, 0x17, 0x0006, 0x0000);
3054 rtl_writephy(tp, 0x1f, 0x0000);
3055
3056 /* For impedance matching */
3057 rtl_writephy(tp, 0x1f, 0x0002);
3058 rtl_w1w0_phy(tp, 0x08, 0x8000, 0x7f00);
Francois Romieucecb5fd2011-04-01 10:21:07 +02003059 rtl_writephy(tp, 0x1f, 0x0000);
hayeswang01dc7fe2011-03-21 01:50:28 +00003060
3061 /* PHY auto speed down */
3062 rtl_writephy(tp, 0x1f, 0x0007);
3063 rtl_writephy(tp, 0x1e, 0x002d);
3064 rtl_w1w0_phy(tp, 0x18, 0x0050, 0x0000);
3065 rtl_writephy(tp, 0x1f, 0x0000);
3066 rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000);
3067
3068 rtl_writephy(tp, 0x1f, 0x0005);
3069 rtl_writephy(tp, 0x05, 0x8b86);
3070 rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000);
3071 rtl_writephy(tp, 0x1f, 0x0000);
3072
3073 rtl_writephy(tp, 0x1f, 0x0005);
3074 rtl_writephy(tp, 0x05, 0x8b85);
3075 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x2000);
3076 rtl_writephy(tp, 0x1f, 0x0007);
3077 rtl_writephy(tp, 0x1e, 0x0020);
3078 rtl_w1w0_phy(tp, 0x15, 0x0000, 0x1100);
3079 rtl_writephy(tp, 0x1f, 0x0006);
3080 rtl_writephy(tp, 0x00, 0x5a00);
3081 rtl_writephy(tp, 0x1f, 0x0000);
3082 rtl_writephy(tp, 0x0d, 0x0007);
3083 rtl_writephy(tp, 0x0e, 0x003c);
3084 rtl_writephy(tp, 0x0d, 0x4007);
3085 rtl_writephy(tp, 0x0e, 0x0000);
3086 rtl_writephy(tp, 0x0d, 0x0000);
3087}
3088
françois romieu9ecb9aa2012-12-07 11:20:21 +00003089static void rtl_rar_exgmac_set(struct rtl8169_private *tp, u8 *addr)
3090{
3091 const u16 w[] = {
3092 addr[0] | (addr[1] << 8),
3093 addr[2] | (addr[3] << 8),
3094 addr[4] | (addr[5] << 8)
3095 };
3096 const struct exgmac_reg e[] = {
3097 { .addr = 0xe0, ERIAR_MASK_1111, .val = w[0] | (w[1] << 16) },
3098 { .addr = 0xe4, ERIAR_MASK_1111, .val = w[2] },
3099 { .addr = 0xf0, ERIAR_MASK_1111, .val = w[0] << 16 },
3100 { .addr = 0xf4, ERIAR_MASK_1111, .val = w[1] | (w[2] << 16) }
3101 };
3102
3103 rtl_write_exgmac_batch(tp, e, ARRAY_SIZE(e));
3104}
3105
Hayes Wang70090422011-07-06 15:58:06 +08003106static void rtl8168e_2_hw_phy_config(struct rtl8169_private *tp)
3107{
3108 static const struct phy_reg phy_reg_init[] = {
3109 /* Enable Delay cap */
3110 { 0x1f, 0x0004 },
3111 { 0x1f, 0x0007 },
3112 { 0x1e, 0x00ac },
3113 { 0x18, 0x0006 },
3114 { 0x1f, 0x0002 },
3115 { 0x1f, 0x0000 },
3116 { 0x1f, 0x0000 },
3117
3118 /* Channel estimation fine tune */
3119 { 0x1f, 0x0003 },
3120 { 0x09, 0xa20f },
3121 { 0x1f, 0x0000 },
3122 { 0x1f, 0x0000 },
3123
3124 /* Green Setting */
3125 { 0x1f, 0x0005 },
3126 { 0x05, 0x8b5b },
3127 { 0x06, 0x9222 },
3128 { 0x05, 0x8b6d },
3129 { 0x06, 0x8000 },
3130 { 0x05, 0x8b76 },
3131 { 0x06, 0x8000 },
3132 { 0x1f, 0x0000 }
3133 };
3134
3135 rtl_apply_firmware(tp);
3136
3137 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3138
3139 /* For 4-corner performance improve */
3140 rtl_writephy(tp, 0x1f, 0x0005);
3141 rtl_writephy(tp, 0x05, 0x8b80);
3142 rtl_w1w0_phy(tp, 0x17, 0x0006, 0x0000);
3143 rtl_writephy(tp, 0x1f, 0x0000);
3144
3145 /* PHY auto speed down */
3146 rtl_writephy(tp, 0x1f, 0x0004);
3147 rtl_writephy(tp, 0x1f, 0x0007);
3148 rtl_writephy(tp, 0x1e, 0x002d);
3149 rtl_w1w0_phy(tp, 0x18, 0x0010, 0x0000);
3150 rtl_writephy(tp, 0x1f, 0x0002);
3151 rtl_writephy(tp, 0x1f, 0x0000);
3152 rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000);
3153
3154 /* improve 10M EEE waveform */
3155 rtl_writephy(tp, 0x1f, 0x0005);
3156 rtl_writephy(tp, 0x05, 0x8b86);
3157 rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000);
3158 rtl_writephy(tp, 0x1f, 0x0000);
3159
3160 /* Improve 2-pair detection performance */
3161 rtl_writephy(tp, 0x1f, 0x0005);
3162 rtl_writephy(tp, 0x05, 0x8b85);
3163 rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000);
3164 rtl_writephy(tp, 0x1f, 0x0000);
3165
3166 /* EEE setting */
Francois Romieufdf6fc02012-07-06 22:40:38 +02003167 rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_1111, 0x0000, 0x0003, ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08003168 rtl_writephy(tp, 0x1f, 0x0005);
3169 rtl_writephy(tp, 0x05, 0x8b85);
3170 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x2000);
3171 rtl_writephy(tp, 0x1f, 0x0004);
3172 rtl_writephy(tp, 0x1f, 0x0007);
3173 rtl_writephy(tp, 0x1e, 0x0020);
David S. Miller1805b2f2011-10-24 18:18:09 -04003174 rtl_w1w0_phy(tp, 0x15, 0x0000, 0x0100);
Hayes Wang70090422011-07-06 15:58:06 +08003175 rtl_writephy(tp, 0x1f, 0x0002);
3176 rtl_writephy(tp, 0x1f, 0x0000);
3177 rtl_writephy(tp, 0x0d, 0x0007);
3178 rtl_writephy(tp, 0x0e, 0x003c);
3179 rtl_writephy(tp, 0x0d, 0x4007);
3180 rtl_writephy(tp, 0x0e, 0x0000);
3181 rtl_writephy(tp, 0x0d, 0x0000);
3182
3183 /* Green feature */
3184 rtl_writephy(tp, 0x1f, 0x0003);
3185 rtl_w1w0_phy(tp, 0x19, 0x0000, 0x0001);
3186 rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0400);
3187 rtl_writephy(tp, 0x1f, 0x0000);
hayeswange0c07552012-10-23 20:24:03 +00003188
françois romieu9ecb9aa2012-12-07 11:20:21 +00003189 /* Broken BIOS workaround: feed GigaMAC registers with MAC address. */
3190 rtl_rar_exgmac_set(tp, tp->dev->dev_addr);
Hayes Wang70090422011-07-06 15:58:06 +08003191}
3192
Hayes Wang5f886e02012-03-30 14:33:03 +08003193static void rtl8168f_hw_phy_config(struct rtl8169_private *tp)
3194{
3195 /* For 4-corner performance improve */
3196 rtl_writephy(tp, 0x1f, 0x0005);
3197 rtl_writephy(tp, 0x05, 0x8b80);
3198 rtl_w1w0_phy(tp, 0x06, 0x0006, 0x0000);
3199 rtl_writephy(tp, 0x1f, 0x0000);
3200
3201 /* PHY auto speed down */
3202 rtl_writephy(tp, 0x1f, 0x0007);
3203 rtl_writephy(tp, 0x1e, 0x002d);
3204 rtl_w1w0_phy(tp, 0x18, 0x0010, 0x0000);
3205 rtl_writephy(tp, 0x1f, 0x0000);
3206 rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000);
3207
3208 /* Improve 10M EEE waveform */
3209 rtl_writephy(tp, 0x1f, 0x0005);
3210 rtl_writephy(tp, 0x05, 0x8b86);
3211 rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000);
3212 rtl_writephy(tp, 0x1f, 0x0000);
3213}
3214
Hayes Wangc2218922011-09-06 16:55:18 +08003215static void rtl8168f_1_hw_phy_config(struct rtl8169_private *tp)
3216{
3217 static const struct phy_reg phy_reg_init[] = {
3218 /* Channel estimation fine tune */
3219 { 0x1f, 0x0003 },
3220 { 0x09, 0xa20f },
3221 { 0x1f, 0x0000 },
3222
3223 /* Modify green table for giga & fnet */
3224 { 0x1f, 0x0005 },
3225 { 0x05, 0x8b55 },
3226 { 0x06, 0x0000 },
3227 { 0x05, 0x8b5e },
3228 { 0x06, 0x0000 },
3229 { 0x05, 0x8b67 },
3230 { 0x06, 0x0000 },
3231 { 0x05, 0x8b70 },
3232 { 0x06, 0x0000 },
3233 { 0x1f, 0x0000 },
3234 { 0x1f, 0x0007 },
3235 { 0x1e, 0x0078 },
3236 { 0x17, 0x0000 },
3237 { 0x19, 0x00fb },
3238 { 0x1f, 0x0000 },
3239
3240 /* Modify green table for 10M */
3241 { 0x1f, 0x0005 },
3242 { 0x05, 0x8b79 },
3243 { 0x06, 0xaa00 },
3244 { 0x1f, 0x0000 },
3245
3246 /* Disable hiimpedance detection (RTCT) */
3247 { 0x1f, 0x0003 },
3248 { 0x01, 0x328a },
3249 { 0x1f, 0x0000 }
3250 };
3251
3252 rtl_apply_firmware(tp);
3253
3254 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3255
Hayes Wang5f886e02012-03-30 14:33:03 +08003256 rtl8168f_hw_phy_config(tp);
Hayes Wangc2218922011-09-06 16:55:18 +08003257
3258 /* Improve 2-pair detection performance */
3259 rtl_writephy(tp, 0x1f, 0x0005);
3260 rtl_writephy(tp, 0x05, 0x8b85);
3261 rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000);
3262 rtl_writephy(tp, 0x1f, 0x0000);
3263}
3264
3265static void rtl8168f_2_hw_phy_config(struct rtl8169_private *tp)
3266{
3267 rtl_apply_firmware(tp);
3268
Hayes Wang5f886e02012-03-30 14:33:03 +08003269 rtl8168f_hw_phy_config(tp);
Hayes Wangc2218922011-09-06 16:55:18 +08003270}
3271
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003272static void rtl8411_hw_phy_config(struct rtl8169_private *tp)
3273{
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003274 static const struct phy_reg phy_reg_init[] = {
3275 /* Channel estimation fine tune */
3276 { 0x1f, 0x0003 },
3277 { 0x09, 0xa20f },
3278 { 0x1f, 0x0000 },
3279
3280 /* Modify green table for giga & fnet */
3281 { 0x1f, 0x0005 },
3282 { 0x05, 0x8b55 },
3283 { 0x06, 0x0000 },
3284 { 0x05, 0x8b5e },
3285 { 0x06, 0x0000 },
3286 { 0x05, 0x8b67 },
3287 { 0x06, 0x0000 },
3288 { 0x05, 0x8b70 },
3289 { 0x06, 0x0000 },
3290 { 0x1f, 0x0000 },
3291 { 0x1f, 0x0007 },
3292 { 0x1e, 0x0078 },
3293 { 0x17, 0x0000 },
3294 { 0x19, 0x00aa },
3295 { 0x1f, 0x0000 },
3296
3297 /* Modify green table for 10M */
3298 { 0x1f, 0x0005 },
3299 { 0x05, 0x8b79 },
3300 { 0x06, 0xaa00 },
3301 { 0x1f, 0x0000 },
3302
3303 /* Disable hiimpedance detection (RTCT) */
3304 { 0x1f, 0x0003 },
3305 { 0x01, 0x328a },
3306 { 0x1f, 0x0000 }
3307 };
3308
3309
3310 rtl_apply_firmware(tp);
3311
3312 rtl8168f_hw_phy_config(tp);
3313
3314 /* Improve 2-pair detection performance */
3315 rtl_writephy(tp, 0x1f, 0x0005);
3316 rtl_writephy(tp, 0x05, 0x8b85);
3317 rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000);
3318 rtl_writephy(tp, 0x1f, 0x0000);
3319
3320 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3321
3322 /* Modify green table for giga */
3323 rtl_writephy(tp, 0x1f, 0x0005);
3324 rtl_writephy(tp, 0x05, 0x8b54);
3325 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0800);
3326 rtl_writephy(tp, 0x05, 0x8b5d);
3327 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0800);
3328 rtl_writephy(tp, 0x05, 0x8a7c);
3329 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100);
3330 rtl_writephy(tp, 0x05, 0x8a7f);
3331 rtl_w1w0_phy(tp, 0x06, 0x0100, 0x0000);
3332 rtl_writephy(tp, 0x05, 0x8a82);
3333 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100);
3334 rtl_writephy(tp, 0x05, 0x8a85);
3335 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100);
3336 rtl_writephy(tp, 0x05, 0x8a88);
3337 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100);
3338 rtl_writephy(tp, 0x1f, 0x0000);
3339
3340 /* uc same-seed solution */
3341 rtl_writephy(tp, 0x1f, 0x0005);
3342 rtl_writephy(tp, 0x05, 0x8b85);
3343 rtl_w1w0_phy(tp, 0x06, 0x8000, 0x0000);
3344 rtl_writephy(tp, 0x1f, 0x0000);
3345
3346 /* eee setting */
Francois Romieufdf6fc02012-07-06 22:40:38 +02003347 rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_0001, 0x00, 0x03, ERIAR_EXGMAC);
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003348 rtl_writephy(tp, 0x1f, 0x0005);
3349 rtl_writephy(tp, 0x05, 0x8b85);
3350 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x2000);
3351 rtl_writephy(tp, 0x1f, 0x0004);
3352 rtl_writephy(tp, 0x1f, 0x0007);
3353 rtl_writephy(tp, 0x1e, 0x0020);
3354 rtl_w1w0_phy(tp, 0x15, 0x0000, 0x0100);
3355 rtl_writephy(tp, 0x1f, 0x0000);
3356 rtl_writephy(tp, 0x0d, 0x0007);
3357 rtl_writephy(tp, 0x0e, 0x003c);
3358 rtl_writephy(tp, 0x0d, 0x4007);
3359 rtl_writephy(tp, 0x0e, 0x0000);
3360 rtl_writephy(tp, 0x0d, 0x0000);
3361
3362 /* Green feature */
3363 rtl_writephy(tp, 0x1f, 0x0003);
3364 rtl_w1w0_phy(tp, 0x19, 0x0000, 0x0001);
3365 rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0400);
3366 rtl_writephy(tp, 0x1f, 0x0000);
3367}
3368
Hayes Wangc5583862012-07-02 17:23:22 +08003369static void rtl8168g_1_hw_phy_config(struct rtl8169_private *tp)
3370{
3371 static const u16 mac_ocp_patch[] = {
3372 0xe008, 0xe01b, 0xe01d, 0xe01f,
3373 0xe021, 0xe023, 0xe025, 0xe027,
3374 0x49d2, 0xf10d, 0x766c, 0x49e2,
3375 0xf00a, 0x1ec0, 0x8ee1, 0xc60a,
3376
3377 0x77c0, 0x4870, 0x9fc0, 0x1ea0,
3378 0xc707, 0x8ee1, 0x9d6c, 0xc603,
3379 0xbe00, 0xb416, 0x0076, 0xe86c,
3380 0xc602, 0xbe00, 0x0000, 0xc602,
3381
3382 0xbe00, 0x0000, 0xc602, 0xbe00,
3383 0x0000, 0xc602, 0xbe00, 0x0000,
3384 0xc602, 0xbe00, 0x0000, 0xc602,
3385 0xbe00, 0x0000, 0xc602, 0xbe00,
3386
3387 0x0000, 0x0000, 0x0000, 0x0000
3388 };
3389 u32 i;
3390
3391 /* Patch code for GPHY reset */
3392 for (i = 0; i < ARRAY_SIZE(mac_ocp_patch); i++)
3393 r8168_mac_ocp_write(tp, 0xf800 + 2*i, mac_ocp_patch[i]);
3394 r8168_mac_ocp_write(tp, 0xfc26, 0x8000);
3395 r8168_mac_ocp_write(tp, 0xfc28, 0x0075);
3396
3397 rtl_apply_firmware(tp);
3398
3399 if (r8168_phy_ocp_read(tp, 0xa460) & 0x0100)
3400 rtl_w1w0_phy_ocp(tp, 0xbcc4, 0x0000, 0x8000);
3401 else
3402 rtl_w1w0_phy_ocp(tp, 0xbcc4, 0x8000, 0x0000);
3403
3404 if (r8168_phy_ocp_read(tp, 0xa466) & 0x0100)
3405 rtl_w1w0_phy_ocp(tp, 0xc41a, 0x0002, 0x0000);
3406 else
3407 rtl_w1w0_phy_ocp(tp, 0xbcc4, 0x0000, 0x0002);
3408
3409 rtl_w1w0_phy_ocp(tp, 0xa442, 0x000c, 0x0000);
3410 rtl_w1w0_phy_ocp(tp, 0xa4b2, 0x0004, 0x0000);
3411
3412 r8168_phy_ocp_write(tp, 0xa436, 0x8012);
3413 rtl_w1w0_phy_ocp(tp, 0xa438, 0x8000, 0x0000);
3414
3415 rtl_w1w0_phy_ocp(tp, 0xc422, 0x4000, 0x2000);
3416}
3417
françois romieu4da19632011-01-03 15:07:55 +00003418static void rtl8102e_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu2857ffb2008-08-02 21:08:49 +02003419{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08003420 static const struct phy_reg phy_reg_init[] = {
Francois Romieu2857ffb2008-08-02 21:08:49 +02003421 { 0x1f, 0x0003 },
3422 { 0x08, 0x441d },
3423 { 0x01, 0x9100 },
3424 { 0x1f, 0x0000 }
3425 };
3426
françois romieu4da19632011-01-03 15:07:55 +00003427 rtl_writephy(tp, 0x1f, 0x0000);
3428 rtl_patchphy(tp, 0x11, 1 << 12);
3429 rtl_patchphy(tp, 0x19, 1 << 13);
3430 rtl_patchphy(tp, 0x10, 1 << 15);
Francois Romieu2857ffb2008-08-02 21:08:49 +02003431
françois romieu4da19632011-01-03 15:07:55 +00003432 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu2857ffb2008-08-02 21:08:49 +02003433}
3434
Hayes Wang5a5e4442011-02-22 17:26:21 +08003435static void rtl8105e_hw_phy_config(struct rtl8169_private *tp)
3436{
3437 static const struct phy_reg phy_reg_init[] = {
3438 { 0x1f, 0x0005 },
3439 { 0x1a, 0x0000 },
3440 { 0x1f, 0x0000 },
3441
3442 { 0x1f, 0x0004 },
3443 { 0x1c, 0x0000 },
3444 { 0x1f, 0x0000 },
3445
3446 { 0x1f, 0x0001 },
3447 { 0x15, 0x7701 },
3448 { 0x1f, 0x0000 }
3449 };
3450
3451 /* Disable ALDPS before ram code */
Francois Romieueef63cc2013-02-08 23:43:20 +01003452 rtl_writephy(tp, 0x1f, 0x0000);
3453 rtl_writephy(tp, 0x18, 0x0310);
3454 msleep(100);
Hayes Wang5a5e4442011-02-22 17:26:21 +08003455
François Romieu953a12c2011-04-24 17:38:48 +02003456 rtl_apply_firmware(tp);
Hayes Wang5a5e4442011-02-22 17:26:21 +08003457
3458 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3459}
3460
Hayes Wang7e18dca2012-03-30 14:33:02 +08003461static void rtl8402_hw_phy_config(struct rtl8169_private *tp)
3462{
Hayes Wang7e18dca2012-03-30 14:33:02 +08003463 /* Disable ALDPS before setting firmware */
Francois Romieueef63cc2013-02-08 23:43:20 +01003464 rtl_writephy(tp, 0x1f, 0x0000);
3465 rtl_writephy(tp, 0x18, 0x0310);
3466 msleep(20);
Hayes Wang7e18dca2012-03-30 14:33:02 +08003467
3468 rtl_apply_firmware(tp);
3469
3470 /* EEE setting */
Francois Romieufdf6fc02012-07-06 22:40:38 +02003471 rtl_eri_write(tp, 0x1b0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
Hayes Wang7e18dca2012-03-30 14:33:02 +08003472 rtl_writephy(tp, 0x1f, 0x0004);
3473 rtl_writephy(tp, 0x10, 0x401f);
3474 rtl_writephy(tp, 0x19, 0x7030);
3475 rtl_writephy(tp, 0x1f, 0x0000);
3476}
3477
Hayes Wang5598bfe2012-07-02 17:23:21 +08003478static void rtl8106e_hw_phy_config(struct rtl8169_private *tp)
3479{
Hayes Wang5598bfe2012-07-02 17:23:21 +08003480 static const struct phy_reg phy_reg_init[] = {
3481 { 0x1f, 0x0004 },
3482 { 0x10, 0xc07f },
3483 { 0x19, 0x7030 },
3484 { 0x1f, 0x0000 }
3485 };
3486
3487 /* Disable ALDPS before ram code */
Francois Romieueef63cc2013-02-08 23:43:20 +01003488 rtl_writephy(tp, 0x1f, 0x0000);
3489 rtl_writephy(tp, 0x18, 0x0310);
3490 msleep(100);
Hayes Wang5598bfe2012-07-02 17:23:21 +08003491
3492 rtl_apply_firmware(tp);
3493
Francois Romieufdf6fc02012-07-06 22:40:38 +02003494 rtl_eri_write(tp, 0x1b0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
Hayes Wang5598bfe2012-07-02 17:23:21 +08003495 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3496
Francois Romieufdf6fc02012-07-06 22:40:38 +02003497 rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
Hayes Wang5598bfe2012-07-02 17:23:21 +08003498}
3499
Francois Romieu5615d9f2007-08-17 17:50:46 +02003500static void rtl_hw_phy_config(struct net_device *dev)
3501{
3502 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieu5615d9f2007-08-17 17:50:46 +02003503
3504 rtl8169_print_mac_version(tp);
3505
3506 switch (tp->mac_version) {
3507 case RTL_GIGA_MAC_VER_01:
3508 break;
3509 case RTL_GIGA_MAC_VER_02:
3510 case RTL_GIGA_MAC_VER_03:
françois romieu4da19632011-01-03 15:07:55 +00003511 rtl8169s_hw_phy_config(tp);
Francois Romieu5615d9f2007-08-17 17:50:46 +02003512 break;
3513 case RTL_GIGA_MAC_VER_04:
françois romieu4da19632011-01-03 15:07:55 +00003514 rtl8169sb_hw_phy_config(tp);
Francois Romieu5615d9f2007-08-17 17:50:46 +02003515 break;
françois romieu2e9558562009-08-10 19:44:19 +00003516 case RTL_GIGA_MAC_VER_05:
françois romieu4da19632011-01-03 15:07:55 +00003517 rtl8169scd_hw_phy_config(tp);
françois romieu2e9558562009-08-10 19:44:19 +00003518 break;
françois romieu8c7006a2009-08-10 19:43:29 +00003519 case RTL_GIGA_MAC_VER_06:
françois romieu4da19632011-01-03 15:07:55 +00003520 rtl8169sce_hw_phy_config(tp);
françois romieu8c7006a2009-08-10 19:43:29 +00003521 break;
Francois Romieu2857ffb2008-08-02 21:08:49 +02003522 case RTL_GIGA_MAC_VER_07:
3523 case RTL_GIGA_MAC_VER_08:
3524 case RTL_GIGA_MAC_VER_09:
françois romieu4da19632011-01-03 15:07:55 +00003525 rtl8102e_hw_phy_config(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02003526 break;
Francois Romieu236b8082008-05-30 16:11:48 +02003527 case RTL_GIGA_MAC_VER_11:
françois romieu4da19632011-01-03 15:07:55 +00003528 rtl8168bb_hw_phy_config(tp);
Francois Romieu236b8082008-05-30 16:11:48 +02003529 break;
3530 case RTL_GIGA_MAC_VER_12:
françois romieu4da19632011-01-03 15:07:55 +00003531 rtl8168bef_hw_phy_config(tp);
Francois Romieu236b8082008-05-30 16:11:48 +02003532 break;
3533 case RTL_GIGA_MAC_VER_17:
françois romieu4da19632011-01-03 15:07:55 +00003534 rtl8168bef_hw_phy_config(tp);
Francois Romieu236b8082008-05-30 16:11:48 +02003535 break;
Francois Romieu867763c2007-08-17 18:21:58 +02003536 case RTL_GIGA_MAC_VER_18:
françois romieu4da19632011-01-03 15:07:55 +00003537 rtl8168cp_1_hw_phy_config(tp);
Francois Romieu867763c2007-08-17 18:21:58 +02003538 break;
3539 case RTL_GIGA_MAC_VER_19:
françois romieu4da19632011-01-03 15:07:55 +00003540 rtl8168c_1_hw_phy_config(tp);
Francois Romieu867763c2007-08-17 18:21:58 +02003541 break;
Francois Romieu7da97ec2007-10-18 15:20:43 +02003542 case RTL_GIGA_MAC_VER_20:
françois romieu4da19632011-01-03 15:07:55 +00003543 rtl8168c_2_hw_phy_config(tp);
Francois Romieu7da97ec2007-10-18 15:20:43 +02003544 break;
Francois Romieu197ff762008-06-28 13:16:02 +02003545 case RTL_GIGA_MAC_VER_21:
françois romieu4da19632011-01-03 15:07:55 +00003546 rtl8168c_3_hw_phy_config(tp);
Francois Romieu197ff762008-06-28 13:16:02 +02003547 break;
Francois Romieu6fb07052008-06-29 11:54:28 +02003548 case RTL_GIGA_MAC_VER_22:
françois romieu4da19632011-01-03 15:07:55 +00003549 rtl8168c_4_hw_phy_config(tp);
Francois Romieu6fb07052008-06-29 11:54:28 +02003550 break;
Francois Romieuef3386f2008-06-29 12:24:30 +02003551 case RTL_GIGA_MAC_VER_23:
Francois Romieu7f3e3d32008-07-20 18:53:20 +02003552 case RTL_GIGA_MAC_VER_24:
françois romieu4da19632011-01-03 15:07:55 +00003553 rtl8168cp_2_hw_phy_config(tp);
Francois Romieuef3386f2008-06-29 12:24:30 +02003554 break;
Francois Romieu5b538df2008-07-20 16:22:45 +02003555 case RTL_GIGA_MAC_VER_25:
françois romieubca03d52011-01-03 15:07:31 +00003556 rtl8168d_1_hw_phy_config(tp);
françois romieudaf9df62009-10-07 12:44:20 +00003557 break;
3558 case RTL_GIGA_MAC_VER_26:
françois romieubca03d52011-01-03 15:07:31 +00003559 rtl8168d_2_hw_phy_config(tp);
françois romieudaf9df62009-10-07 12:44:20 +00003560 break;
3561 case RTL_GIGA_MAC_VER_27:
françois romieu4da19632011-01-03 15:07:55 +00003562 rtl8168d_3_hw_phy_config(tp);
Francois Romieu5b538df2008-07-20 16:22:45 +02003563 break;
françois romieue6de30d2011-01-03 15:08:37 +00003564 case RTL_GIGA_MAC_VER_28:
3565 rtl8168d_4_hw_phy_config(tp);
3566 break;
Hayes Wang5a5e4442011-02-22 17:26:21 +08003567 case RTL_GIGA_MAC_VER_29:
3568 case RTL_GIGA_MAC_VER_30:
3569 rtl8105e_hw_phy_config(tp);
3570 break;
Francois Romieucecb5fd2011-04-01 10:21:07 +02003571 case RTL_GIGA_MAC_VER_31:
3572 /* None. */
3573 break;
hayeswang01dc7fe2011-03-21 01:50:28 +00003574 case RTL_GIGA_MAC_VER_32:
hayeswang01dc7fe2011-03-21 01:50:28 +00003575 case RTL_GIGA_MAC_VER_33:
Hayes Wang70090422011-07-06 15:58:06 +08003576 rtl8168e_1_hw_phy_config(tp);
3577 break;
3578 case RTL_GIGA_MAC_VER_34:
3579 rtl8168e_2_hw_phy_config(tp);
hayeswang01dc7fe2011-03-21 01:50:28 +00003580 break;
Hayes Wangc2218922011-09-06 16:55:18 +08003581 case RTL_GIGA_MAC_VER_35:
3582 rtl8168f_1_hw_phy_config(tp);
3583 break;
3584 case RTL_GIGA_MAC_VER_36:
3585 rtl8168f_2_hw_phy_config(tp);
3586 break;
Francois Romieuef3386f2008-06-29 12:24:30 +02003587
Hayes Wang7e18dca2012-03-30 14:33:02 +08003588 case RTL_GIGA_MAC_VER_37:
3589 rtl8402_hw_phy_config(tp);
3590 break;
3591
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003592 case RTL_GIGA_MAC_VER_38:
3593 rtl8411_hw_phy_config(tp);
3594 break;
3595
Hayes Wang5598bfe2012-07-02 17:23:21 +08003596 case RTL_GIGA_MAC_VER_39:
3597 rtl8106e_hw_phy_config(tp);
3598 break;
3599
Hayes Wangc5583862012-07-02 17:23:22 +08003600 case RTL_GIGA_MAC_VER_40:
3601 rtl8168g_1_hw_phy_config(tp);
3602 break;
3603
3604 case RTL_GIGA_MAC_VER_41:
Francois Romieu5615d9f2007-08-17 17:50:46 +02003605 default:
3606 break;
3607 }
3608}
3609
Francois Romieuda78dbf2012-01-26 14:18:23 +01003610static void rtl_phy_work(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003611{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003612 struct timer_list *timer = &tp->timer;
3613 void __iomem *ioaddr = tp->mmio_addr;
3614 unsigned long timeout = RTL8169_PHY_TIMEOUT;
3615
Francois Romieubcf0bf92006-07-26 23:14:13 +02003616 assert(tp->mac_version > RTL_GIGA_MAC_VER_01);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003617
françois romieu4da19632011-01-03 15:07:55 +00003618 if (tp->phy_reset_pending(tp)) {
Francois Romieu5b0384f2006-08-16 16:00:01 +02003619 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07003620 * A busy loop could burn quite a few cycles on nowadays CPU.
3621 * Let's delay the execution of the timer for a few ticks.
3622 */
3623 timeout = HZ/10;
3624 goto out_mod_timer;
3625 }
3626
3627 if (tp->link_ok(ioaddr))
Francois Romieuda78dbf2012-01-26 14:18:23 +01003628 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003629
Francois Romieuda78dbf2012-01-26 14:18:23 +01003630 netif_warn(tp, link, tp->dev, "PHY reset until link up\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003631
françois romieu4da19632011-01-03 15:07:55 +00003632 tp->phy_reset_enable(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003633
3634out_mod_timer:
3635 mod_timer(timer, jiffies + timeout);
Francois Romieuda78dbf2012-01-26 14:18:23 +01003636}
3637
3638static void rtl_schedule_task(struct rtl8169_private *tp, enum rtl_flag flag)
3639{
Francois Romieuda78dbf2012-01-26 14:18:23 +01003640 if (!test_and_set_bit(flag, tp->wk.flags))
3641 schedule_work(&tp->wk.work);
Francois Romieuda78dbf2012-01-26 14:18:23 +01003642}
3643
3644static void rtl8169_phy_timer(unsigned long __opaque)
3645{
3646 struct net_device *dev = (struct net_device *)__opaque;
3647 struct rtl8169_private *tp = netdev_priv(dev);
3648
Francois Romieu98ddf982012-01-31 10:47:34 +01003649 rtl_schedule_task(tp, RTL_FLAG_TASK_PHY_PENDING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003650}
3651
Linus Torvalds1da177e2005-04-16 15:20:36 -07003652static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev,
3653 void __iomem *ioaddr)
3654{
3655 iounmap(ioaddr);
3656 pci_release_regions(pdev);
françois romieu87aeec72010-04-26 11:42:06 +00003657 pci_clear_mwi(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003658 pci_disable_device(pdev);
3659 free_netdev(dev);
3660}
3661
Francois Romieuffc46952012-07-06 14:19:23 +02003662DECLARE_RTL_COND(rtl_phy_reset_cond)
3663{
3664 return tp->phy_reset_pending(tp);
3665}
3666
Francois Romieubf793292006-11-01 00:53:05 +01003667static void rtl8169_phy_reset(struct net_device *dev,
3668 struct rtl8169_private *tp)
3669{
françois romieu4da19632011-01-03 15:07:55 +00003670 tp->phy_reset_enable(tp);
Francois Romieuffc46952012-07-06 14:19:23 +02003671 rtl_msleep_loop_wait_low(tp, &rtl_phy_reset_cond, 1, 100);
Francois Romieubf793292006-11-01 00:53:05 +01003672}
3673
David S. Miller8decf862011-09-22 03:23:13 -04003674static bool rtl_tbi_enabled(struct rtl8169_private *tp)
3675{
3676 void __iomem *ioaddr = tp->mmio_addr;
3677
3678 return (tp->mac_version == RTL_GIGA_MAC_VER_01) &&
3679 (RTL_R8(PHYstatus) & TBI_Enable);
3680}
3681
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003682static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003683{
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003684 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003685
Francois Romieu5615d9f2007-08-17 17:50:46 +02003686 rtl_hw_phy_config(dev);
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003687
Marcus Sundberg773328942008-07-10 21:28:08 +02003688 if (tp->mac_version <= RTL_GIGA_MAC_VER_06) {
3689 dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
3690 RTL_W8(0x82, 0x01);
3691 }
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003692
Francois Romieu6dccd162007-02-13 23:38:05 +01003693 pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40);
3694
3695 if (tp->mac_version <= RTL_GIGA_MAC_VER_06)
3696 pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08);
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003697
Francois Romieubcf0bf92006-07-26 23:14:13 +02003698 if (tp->mac_version == RTL_GIGA_MAC_VER_02) {
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003699 dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
3700 RTL_W8(0x82, 0x01);
3701 dprintk("Set PHY Reg 0x0bh = 0x00h\n");
françois romieu4da19632011-01-03 15:07:55 +00003702 rtl_writephy(tp, 0x0b, 0x0000); //w 0x0b 15 0 0
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003703 }
3704
Francois Romieubf793292006-11-01 00:53:05 +01003705 rtl8169_phy_reset(dev, tp);
3706
Oliver Neukum54405cd2011-01-06 21:55:13 +01003707 rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL,
Francois Romieucecb5fd2011-04-01 10:21:07 +02003708 ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
3709 ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |
3710 (tp->mii.supports_gmii ?
3711 ADVERTISED_1000baseT_Half |
3712 ADVERTISED_1000baseT_Full : 0));
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003713
David S. Miller8decf862011-09-22 03:23:13 -04003714 if (rtl_tbi_enabled(tp))
Joe Perchesbf82c182010-02-09 11:49:50 +00003715 netif_info(tp, link, dev, "TBI auto-negotiating\n");
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003716}
3717
Francois Romieu773d2022007-01-31 23:47:43 +01003718static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr)
3719{
3720 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu773d2022007-01-31 23:47:43 +01003721
Francois Romieuda78dbf2012-01-26 14:18:23 +01003722 rtl_lock_work(tp);
Francois Romieu773d2022007-01-31 23:47:43 +01003723
3724 RTL_W8(Cfg9346, Cfg9346_Unlock);
françois romieu908ba2bf2010-04-26 11:42:58 +00003725
françois romieu9ecb9aa2012-12-07 11:20:21 +00003726 RTL_W32(MAC4, addr[4] | addr[5] << 8);
françois romieu908ba2bf2010-04-26 11:42:58 +00003727 RTL_R32(MAC4);
3728
françois romieu9ecb9aa2012-12-07 11:20:21 +00003729 RTL_W32(MAC0, addr[0] | addr[1] << 8 | addr[2] << 16 | addr[3] << 24);
françois romieu908ba2bf2010-04-26 11:42:58 +00003730 RTL_R32(MAC0);
3731
françois romieu9ecb9aa2012-12-07 11:20:21 +00003732 if (tp->mac_version == RTL_GIGA_MAC_VER_34)
3733 rtl_rar_exgmac_set(tp, addr);
françois romieuc28aa382011-08-02 03:53:43 +00003734
Francois Romieu773d2022007-01-31 23:47:43 +01003735 RTL_W8(Cfg9346, Cfg9346_Lock);
3736
Francois Romieuda78dbf2012-01-26 14:18:23 +01003737 rtl_unlock_work(tp);
Francois Romieu773d2022007-01-31 23:47:43 +01003738}
3739
3740static int rtl_set_mac_address(struct net_device *dev, void *p)
3741{
3742 struct rtl8169_private *tp = netdev_priv(dev);
3743 struct sockaddr *addr = p;
3744
3745 if (!is_valid_ether_addr(addr->sa_data))
3746 return -EADDRNOTAVAIL;
3747
3748 memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
3749
3750 rtl_rar_set(tp, dev->dev_addr);
3751
3752 return 0;
3753}
3754
Francois Romieu5f787a12006-08-17 13:02:36 +02003755static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
3756{
3757 struct rtl8169_private *tp = netdev_priv(dev);
3758 struct mii_ioctl_data *data = if_mii(ifr);
3759
Francois Romieu8b4ab282008-11-19 22:05:25 -08003760 return netif_running(dev) ? tp->do_ioctl(tp, data, cmd) : -ENODEV;
3761}
Francois Romieu5f787a12006-08-17 13:02:36 +02003762
Francois Romieucecb5fd2011-04-01 10:21:07 +02003763static int rtl_xmii_ioctl(struct rtl8169_private *tp,
3764 struct mii_ioctl_data *data, int cmd)
Francois Romieu8b4ab282008-11-19 22:05:25 -08003765{
Francois Romieu5f787a12006-08-17 13:02:36 +02003766 switch (cmd) {
3767 case SIOCGMIIPHY:
3768 data->phy_id = 32; /* Internal PHY */
3769 return 0;
3770
3771 case SIOCGMIIREG:
françois romieu4da19632011-01-03 15:07:55 +00003772 data->val_out = rtl_readphy(tp, data->reg_num & 0x1f);
Francois Romieu5f787a12006-08-17 13:02:36 +02003773 return 0;
3774
3775 case SIOCSMIIREG:
françois romieu4da19632011-01-03 15:07:55 +00003776 rtl_writephy(tp, data->reg_num & 0x1f, data->val_in);
Francois Romieu5f787a12006-08-17 13:02:36 +02003777 return 0;
3778 }
3779 return -EOPNOTSUPP;
3780}
3781
Francois Romieu8b4ab282008-11-19 22:05:25 -08003782static int rtl_tbi_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd)
3783{
3784 return -EOPNOTSUPP;
3785}
3786
Francois Romieufbac58f2007-10-04 22:51:38 +02003787static void rtl_disable_msi(struct pci_dev *pdev, struct rtl8169_private *tp)
3788{
3789 if (tp->features & RTL_FEATURE_MSI) {
3790 pci_disable_msi(pdev);
3791 tp->features &= ~RTL_FEATURE_MSI;
3792 }
3793}
3794
Bill Pembertonbaf63292012-12-03 09:23:28 -05003795static void rtl_init_mdio_ops(struct rtl8169_private *tp)
françois romieuc0e45c12011-01-03 15:08:04 +00003796{
3797 struct mdio_ops *ops = &tp->mdio_ops;
3798
3799 switch (tp->mac_version) {
3800 case RTL_GIGA_MAC_VER_27:
3801 ops->write = r8168dp_1_mdio_write;
3802 ops->read = r8168dp_1_mdio_read;
3803 break;
françois romieue6de30d2011-01-03 15:08:37 +00003804 case RTL_GIGA_MAC_VER_28:
hayeswang4804b3b2011-03-21 01:50:29 +00003805 case RTL_GIGA_MAC_VER_31:
françois romieue6de30d2011-01-03 15:08:37 +00003806 ops->write = r8168dp_2_mdio_write;
3807 ops->read = r8168dp_2_mdio_read;
3808 break;
Hayes Wangc5583862012-07-02 17:23:22 +08003809 case RTL_GIGA_MAC_VER_40:
3810 case RTL_GIGA_MAC_VER_41:
3811 ops->write = r8168g_mdio_write;
3812 ops->read = r8168g_mdio_read;
3813 break;
françois romieuc0e45c12011-01-03 15:08:04 +00003814 default:
3815 ops->write = r8169_mdio_write;
3816 ops->read = r8169_mdio_read;
3817 break;
3818 }
3819}
3820
David S. Miller1805b2f2011-10-24 18:18:09 -04003821static void rtl_wol_suspend_quirk(struct rtl8169_private *tp)
3822{
3823 void __iomem *ioaddr = tp->mmio_addr;
3824
3825 switch (tp->mac_version) {
Cyril Bruleboisb00e69d2012-10-31 14:00:46 +00003826 case RTL_GIGA_MAC_VER_25:
3827 case RTL_GIGA_MAC_VER_26:
David S. Miller1805b2f2011-10-24 18:18:09 -04003828 case RTL_GIGA_MAC_VER_29:
3829 case RTL_GIGA_MAC_VER_30:
3830 case RTL_GIGA_MAC_VER_32:
3831 case RTL_GIGA_MAC_VER_33:
3832 case RTL_GIGA_MAC_VER_34:
Hayes Wang7e18dca2012-03-30 14:33:02 +08003833 case RTL_GIGA_MAC_VER_37:
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003834 case RTL_GIGA_MAC_VER_38:
Hayes Wang5598bfe2012-07-02 17:23:21 +08003835 case RTL_GIGA_MAC_VER_39:
Hayes Wangc5583862012-07-02 17:23:22 +08003836 case RTL_GIGA_MAC_VER_40:
3837 case RTL_GIGA_MAC_VER_41:
David S. Miller1805b2f2011-10-24 18:18:09 -04003838 RTL_W32(RxConfig, RTL_R32(RxConfig) |
3839 AcceptBroadcast | AcceptMulticast | AcceptMyPhys);
3840 break;
3841 default:
3842 break;
3843 }
3844}
3845
3846static bool rtl_wol_pll_power_down(struct rtl8169_private *tp)
3847{
3848 if (!(__rtl8169_get_wol(tp) & WAKE_ANY))
3849 return false;
3850
3851 rtl_writephy(tp, 0x1f, 0x0000);
3852 rtl_writephy(tp, MII_BMCR, 0x0000);
3853
3854 rtl_wol_suspend_quirk(tp);
3855
3856 return true;
3857}
3858
françois romieu065c27c2011-01-03 15:08:12 +00003859static void r810x_phy_power_down(struct rtl8169_private *tp)
3860{
3861 rtl_writephy(tp, 0x1f, 0x0000);
3862 rtl_writephy(tp, MII_BMCR, BMCR_PDOWN);
3863}
3864
3865static void r810x_phy_power_up(struct rtl8169_private *tp)
3866{
3867 rtl_writephy(tp, 0x1f, 0x0000);
3868 rtl_writephy(tp, MII_BMCR, BMCR_ANENABLE);
3869}
3870
3871static void r810x_pll_power_down(struct rtl8169_private *tp)
3872{
Hayes Wang00042992012-03-30 14:33:00 +08003873 void __iomem *ioaddr = tp->mmio_addr;
3874
David S. Miller1805b2f2011-10-24 18:18:09 -04003875 if (rtl_wol_pll_power_down(tp))
françois romieu065c27c2011-01-03 15:08:12 +00003876 return;
françois romieu065c27c2011-01-03 15:08:12 +00003877
3878 r810x_phy_power_down(tp);
Hayes Wang00042992012-03-30 14:33:00 +08003879
3880 switch (tp->mac_version) {
3881 case RTL_GIGA_MAC_VER_07:
3882 case RTL_GIGA_MAC_VER_08:
3883 case RTL_GIGA_MAC_VER_09:
3884 case RTL_GIGA_MAC_VER_10:
3885 case RTL_GIGA_MAC_VER_13:
3886 case RTL_GIGA_MAC_VER_16:
3887 break;
3888 default:
3889 RTL_W8(PMCH, RTL_R8(PMCH) & ~0x80);
3890 break;
3891 }
françois romieu065c27c2011-01-03 15:08:12 +00003892}
3893
3894static void r810x_pll_power_up(struct rtl8169_private *tp)
3895{
Hayes Wang00042992012-03-30 14:33:00 +08003896 void __iomem *ioaddr = tp->mmio_addr;
3897
françois romieu065c27c2011-01-03 15:08:12 +00003898 r810x_phy_power_up(tp);
Hayes Wang00042992012-03-30 14:33:00 +08003899
3900 switch (tp->mac_version) {
3901 case RTL_GIGA_MAC_VER_07:
3902 case RTL_GIGA_MAC_VER_08:
3903 case RTL_GIGA_MAC_VER_09:
3904 case RTL_GIGA_MAC_VER_10:
3905 case RTL_GIGA_MAC_VER_13:
3906 case RTL_GIGA_MAC_VER_16:
3907 break;
3908 default:
3909 RTL_W8(PMCH, RTL_R8(PMCH) | 0x80);
3910 break;
3911 }
françois romieu065c27c2011-01-03 15:08:12 +00003912}
3913
3914static void r8168_phy_power_up(struct rtl8169_private *tp)
3915{
3916 rtl_writephy(tp, 0x1f, 0x0000);
hayeswang01dc7fe2011-03-21 01:50:28 +00003917 switch (tp->mac_version) {
3918 case RTL_GIGA_MAC_VER_11:
3919 case RTL_GIGA_MAC_VER_12:
3920 case RTL_GIGA_MAC_VER_17:
3921 case RTL_GIGA_MAC_VER_18:
3922 case RTL_GIGA_MAC_VER_19:
3923 case RTL_GIGA_MAC_VER_20:
3924 case RTL_GIGA_MAC_VER_21:
3925 case RTL_GIGA_MAC_VER_22:
3926 case RTL_GIGA_MAC_VER_23:
3927 case RTL_GIGA_MAC_VER_24:
3928 case RTL_GIGA_MAC_VER_25:
3929 case RTL_GIGA_MAC_VER_26:
3930 case RTL_GIGA_MAC_VER_27:
3931 case RTL_GIGA_MAC_VER_28:
3932 case RTL_GIGA_MAC_VER_31:
3933 rtl_writephy(tp, 0x0e, 0x0000);
3934 break;
3935 default:
3936 break;
3937 }
françois romieu065c27c2011-01-03 15:08:12 +00003938 rtl_writephy(tp, MII_BMCR, BMCR_ANENABLE);
3939}
3940
3941static void r8168_phy_power_down(struct rtl8169_private *tp)
3942{
3943 rtl_writephy(tp, 0x1f, 0x0000);
hayeswang01dc7fe2011-03-21 01:50:28 +00003944 switch (tp->mac_version) {
3945 case RTL_GIGA_MAC_VER_32:
3946 case RTL_GIGA_MAC_VER_33:
3947 rtl_writephy(tp, MII_BMCR, BMCR_ANENABLE | BMCR_PDOWN);
3948 break;
3949
3950 case RTL_GIGA_MAC_VER_11:
3951 case RTL_GIGA_MAC_VER_12:
3952 case RTL_GIGA_MAC_VER_17:
3953 case RTL_GIGA_MAC_VER_18:
3954 case RTL_GIGA_MAC_VER_19:
3955 case RTL_GIGA_MAC_VER_20:
3956 case RTL_GIGA_MAC_VER_21:
3957 case RTL_GIGA_MAC_VER_22:
3958 case RTL_GIGA_MAC_VER_23:
3959 case RTL_GIGA_MAC_VER_24:
3960 case RTL_GIGA_MAC_VER_25:
3961 case RTL_GIGA_MAC_VER_26:
3962 case RTL_GIGA_MAC_VER_27:
3963 case RTL_GIGA_MAC_VER_28:
3964 case RTL_GIGA_MAC_VER_31:
3965 rtl_writephy(tp, 0x0e, 0x0200);
3966 default:
3967 rtl_writephy(tp, MII_BMCR, BMCR_PDOWN);
3968 break;
3969 }
françois romieu065c27c2011-01-03 15:08:12 +00003970}
3971
3972static void r8168_pll_power_down(struct rtl8169_private *tp)
3973{
3974 void __iomem *ioaddr = tp->mmio_addr;
3975
Francois Romieucecb5fd2011-04-01 10:21:07 +02003976 if ((tp->mac_version == RTL_GIGA_MAC_VER_27 ||
3977 tp->mac_version == RTL_GIGA_MAC_VER_28 ||
3978 tp->mac_version == RTL_GIGA_MAC_VER_31) &&
hayeswang4804b3b2011-03-21 01:50:29 +00003979 r8168dp_check_dash(tp)) {
françois romieu065c27c2011-01-03 15:08:12 +00003980 return;
Hayes Wang5d2e1952011-02-22 17:26:22 +08003981 }
françois romieu065c27c2011-01-03 15:08:12 +00003982
Francois Romieucecb5fd2011-04-01 10:21:07 +02003983 if ((tp->mac_version == RTL_GIGA_MAC_VER_23 ||
3984 tp->mac_version == RTL_GIGA_MAC_VER_24) &&
françois romieu065c27c2011-01-03 15:08:12 +00003985 (RTL_R16(CPlusCmd) & ASF)) {
3986 return;
3987 }
3988
hayeswang01dc7fe2011-03-21 01:50:28 +00003989 if (tp->mac_version == RTL_GIGA_MAC_VER_32 ||
3990 tp->mac_version == RTL_GIGA_MAC_VER_33)
Francois Romieufdf6fc02012-07-06 22:40:38 +02003991 rtl_ephy_write(tp, 0x19, 0xff64);
hayeswang01dc7fe2011-03-21 01:50:28 +00003992
David S. Miller1805b2f2011-10-24 18:18:09 -04003993 if (rtl_wol_pll_power_down(tp))
françois romieu065c27c2011-01-03 15:08:12 +00003994 return;
françois romieu065c27c2011-01-03 15:08:12 +00003995
3996 r8168_phy_power_down(tp);
3997
3998 switch (tp->mac_version) {
3999 case RTL_GIGA_MAC_VER_25:
4000 case RTL_GIGA_MAC_VER_26:
Hayes Wang5d2e1952011-02-22 17:26:22 +08004001 case RTL_GIGA_MAC_VER_27:
4002 case RTL_GIGA_MAC_VER_28:
hayeswang4804b3b2011-03-21 01:50:29 +00004003 case RTL_GIGA_MAC_VER_31:
hayeswang01dc7fe2011-03-21 01:50:28 +00004004 case RTL_GIGA_MAC_VER_32:
4005 case RTL_GIGA_MAC_VER_33:
françois romieu065c27c2011-01-03 15:08:12 +00004006 RTL_W8(PMCH, RTL_R8(PMCH) & ~0x80);
4007 break;
4008 }
4009}
4010
4011static void r8168_pll_power_up(struct rtl8169_private *tp)
4012{
4013 void __iomem *ioaddr = tp->mmio_addr;
4014
françois romieu065c27c2011-01-03 15:08:12 +00004015 switch (tp->mac_version) {
4016 case RTL_GIGA_MAC_VER_25:
4017 case RTL_GIGA_MAC_VER_26:
Hayes Wang5d2e1952011-02-22 17:26:22 +08004018 case RTL_GIGA_MAC_VER_27:
4019 case RTL_GIGA_MAC_VER_28:
hayeswang4804b3b2011-03-21 01:50:29 +00004020 case RTL_GIGA_MAC_VER_31:
hayeswang01dc7fe2011-03-21 01:50:28 +00004021 case RTL_GIGA_MAC_VER_32:
4022 case RTL_GIGA_MAC_VER_33:
françois romieu065c27c2011-01-03 15:08:12 +00004023 RTL_W8(PMCH, RTL_R8(PMCH) | 0x80);
4024 break;
4025 }
4026
4027 r8168_phy_power_up(tp);
4028}
4029
Francois Romieud58d46b2011-05-03 16:38:29 +02004030static void rtl_generic_op(struct rtl8169_private *tp,
4031 void (*op)(struct rtl8169_private *))
françois romieu065c27c2011-01-03 15:08:12 +00004032{
4033 if (op)
4034 op(tp);
4035}
4036
4037static void rtl_pll_power_down(struct rtl8169_private *tp)
4038{
Francois Romieud58d46b2011-05-03 16:38:29 +02004039 rtl_generic_op(tp, tp->pll_power_ops.down);
françois romieu065c27c2011-01-03 15:08:12 +00004040}
4041
4042static void rtl_pll_power_up(struct rtl8169_private *tp)
4043{
Francois Romieud58d46b2011-05-03 16:38:29 +02004044 rtl_generic_op(tp, tp->pll_power_ops.up);
françois romieu065c27c2011-01-03 15:08:12 +00004045}
4046
Bill Pembertonbaf63292012-12-03 09:23:28 -05004047static void rtl_init_pll_power_ops(struct rtl8169_private *tp)
françois romieu065c27c2011-01-03 15:08:12 +00004048{
4049 struct pll_power_ops *ops = &tp->pll_power_ops;
4050
4051 switch (tp->mac_version) {
4052 case RTL_GIGA_MAC_VER_07:
4053 case RTL_GIGA_MAC_VER_08:
4054 case RTL_GIGA_MAC_VER_09:
4055 case RTL_GIGA_MAC_VER_10:
4056 case RTL_GIGA_MAC_VER_16:
Hayes Wang5a5e4442011-02-22 17:26:21 +08004057 case RTL_GIGA_MAC_VER_29:
4058 case RTL_GIGA_MAC_VER_30:
Hayes Wang7e18dca2012-03-30 14:33:02 +08004059 case RTL_GIGA_MAC_VER_37:
Hayes Wang5598bfe2012-07-02 17:23:21 +08004060 case RTL_GIGA_MAC_VER_39:
françois romieu065c27c2011-01-03 15:08:12 +00004061 ops->down = r810x_pll_power_down;
4062 ops->up = r810x_pll_power_up;
4063 break;
4064
4065 case RTL_GIGA_MAC_VER_11:
4066 case RTL_GIGA_MAC_VER_12:
4067 case RTL_GIGA_MAC_VER_17:
4068 case RTL_GIGA_MAC_VER_18:
4069 case RTL_GIGA_MAC_VER_19:
4070 case RTL_GIGA_MAC_VER_20:
4071 case RTL_GIGA_MAC_VER_21:
4072 case RTL_GIGA_MAC_VER_22:
4073 case RTL_GIGA_MAC_VER_23:
4074 case RTL_GIGA_MAC_VER_24:
4075 case RTL_GIGA_MAC_VER_25:
4076 case RTL_GIGA_MAC_VER_26:
4077 case RTL_GIGA_MAC_VER_27:
françois romieue6de30d2011-01-03 15:08:37 +00004078 case RTL_GIGA_MAC_VER_28:
hayeswang4804b3b2011-03-21 01:50:29 +00004079 case RTL_GIGA_MAC_VER_31:
hayeswang01dc7fe2011-03-21 01:50:28 +00004080 case RTL_GIGA_MAC_VER_32:
4081 case RTL_GIGA_MAC_VER_33:
Hayes Wang70090422011-07-06 15:58:06 +08004082 case RTL_GIGA_MAC_VER_34:
Hayes Wangc2218922011-09-06 16:55:18 +08004083 case RTL_GIGA_MAC_VER_35:
4084 case RTL_GIGA_MAC_VER_36:
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08004085 case RTL_GIGA_MAC_VER_38:
Hayes Wangc5583862012-07-02 17:23:22 +08004086 case RTL_GIGA_MAC_VER_40:
4087 case RTL_GIGA_MAC_VER_41:
françois romieu065c27c2011-01-03 15:08:12 +00004088 ops->down = r8168_pll_power_down;
4089 ops->up = r8168_pll_power_up;
4090 break;
4091
4092 default:
4093 ops->down = NULL;
4094 ops->up = NULL;
4095 break;
4096 }
4097}
4098
Hayes Wange542a222011-07-06 15:58:04 +08004099static void rtl_init_rxcfg(struct rtl8169_private *tp)
4100{
4101 void __iomem *ioaddr = tp->mmio_addr;
4102
4103 switch (tp->mac_version) {
4104 case RTL_GIGA_MAC_VER_01:
4105 case RTL_GIGA_MAC_VER_02:
4106 case RTL_GIGA_MAC_VER_03:
4107 case RTL_GIGA_MAC_VER_04:
4108 case RTL_GIGA_MAC_VER_05:
4109 case RTL_GIGA_MAC_VER_06:
4110 case RTL_GIGA_MAC_VER_10:
4111 case RTL_GIGA_MAC_VER_11:
4112 case RTL_GIGA_MAC_VER_12:
4113 case RTL_GIGA_MAC_VER_13:
4114 case RTL_GIGA_MAC_VER_14:
4115 case RTL_GIGA_MAC_VER_15:
4116 case RTL_GIGA_MAC_VER_16:
4117 case RTL_GIGA_MAC_VER_17:
4118 RTL_W32(RxConfig, RX_FIFO_THRESH | RX_DMA_BURST);
4119 break;
4120 case RTL_GIGA_MAC_VER_18:
4121 case RTL_GIGA_MAC_VER_19:
4122 case RTL_GIGA_MAC_VER_20:
4123 case RTL_GIGA_MAC_VER_21:
4124 case RTL_GIGA_MAC_VER_22:
4125 case RTL_GIGA_MAC_VER_23:
4126 case RTL_GIGA_MAC_VER_24:
françois romieueb2dc352012-06-20 12:09:18 +00004127 case RTL_GIGA_MAC_VER_34:
Hayes Wange542a222011-07-06 15:58:04 +08004128 RTL_W32(RxConfig, RX128_INT_EN | RX_MULTI_EN | RX_DMA_BURST);
4129 break;
4130 default:
4131 RTL_W32(RxConfig, RX128_INT_EN | RX_DMA_BURST);
4132 break;
4133 }
4134}
4135
Hayes Wang92fc43b2011-07-06 15:58:03 +08004136static void rtl8169_init_ring_indexes(struct rtl8169_private *tp)
4137{
Timo Teräs9fba0812013-01-15 21:01:24 +00004138 tp->dirty_tx = tp->cur_tx = tp->cur_rx = 0;
Hayes Wang92fc43b2011-07-06 15:58:03 +08004139}
4140
Francois Romieud58d46b2011-05-03 16:38:29 +02004141static void rtl_hw_jumbo_enable(struct rtl8169_private *tp)
4142{
françois romieu9c5028e2012-03-02 04:43:14 +00004143 void __iomem *ioaddr = tp->mmio_addr;
4144
4145 RTL_W8(Cfg9346, Cfg9346_Unlock);
Francois Romieud58d46b2011-05-03 16:38:29 +02004146 rtl_generic_op(tp, tp->jumbo_ops.enable);
françois romieu9c5028e2012-03-02 04:43:14 +00004147 RTL_W8(Cfg9346, Cfg9346_Lock);
Francois Romieud58d46b2011-05-03 16:38:29 +02004148}
4149
4150static void rtl_hw_jumbo_disable(struct rtl8169_private *tp)
4151{
françois romieu9c5028e2012-03-02 04:43:14 +00004152 void __iomem *ioaddr = tp->mmio_addr;
4153
4154 RTL_W8(Cfg9346, Cfg9346_Unlock);
Francois Romieud58d46b2011-05-03 16:38:29 +02004155 rtl_generic_op(tp, tp->jumbo_ops.disable);
françois romieu9c5028e2012-03-02 04:43:14 +00004156 RTL_W8(Cfg9346, Cfg9346_Lock);
Francois Romieud58d46b2011-05-03 16:38:29 +02004157}
4158
4159static void r8168c_hw_jumbo_enable(struct rtl8169_private *tp)
4160{
4161 void __iomem *ioaddr = tp->mmio_addr;
4162
4163 RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0);
4164 RTL_W8(Config4, RTL_R8(Config4) | Jumbo_En1);
4165 rtl_tx_performance_tweak(tp->pci_dev, 0x2 << MAX_READ_REQUEST_SHIFT);
4166}
4167
4168static void r8168c_hw_jumbo_disable(struct rtl8169_private *tp)
4169{
4170 void __iomem *ioaddr = tp->mmio_addr;
4171
4172 RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0);
4173 RTL_W8(Config4, RTL_R8(Config4) & ~Jumbo_En1);
4174 rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT);
4175}
4176
4177static void r8168dp_hw_jumbo_enable(struct rtl8169_private *tp)
4178{
4179 void __iomem *ioaddr = tp->mmio_addr;
4180
4181 RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0);
4182}
4183
4184static void r8168dp_hw_jumbo_disable(struct rtl8169_private *tp)
4185{
4186 void __iomem *ioaddr = tp->mmio_addr;
4187
4188 RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0);
4189}
4190
4191static void r8168e_hw_jumbo_enable(struct rtl8169_private *tp)
4192{
4193 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieud58d46b2011-05-03 16:38:29 +02004194
4195 RTL_W8(MaxTxPacketSize, 0x3f);
4196 RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0);
4197 RTL_W8(Config4, RTL_R8(Config4) | 0x01);
Francois Romieu4512ff92011-12-22 18:59:37 +01004198 rtl_tx_performance_tweak(tp->pci_dev, 0x2 << MAX_READ_REQUEST_SHIFT);
Francois Romieud58d46b2011-05-03 16:38:29 +02004199}
4200
4201static void r8168e_hw_jumbo_disable(struct rtl8169_private *tp)
4202{
4203 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieud58d46b2011-05-03 16:38:29 +02004204
4205 RTL_W8(MaxTxPacketSize, 0x0c);
4206 RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0);
4207 RTL_W8(Config4, RTL_R8(Config4) & ~0x01);
Francois Romieu4512ff92011-12-22 18:59:37 +01004208 rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT);
Francois Romieud58d46b2011-05-03 16:38:29 +02004209}
4210
4211static void r8168b_0_hw_jumbo_enable(struct rtl8169_private *tp)
4212{
4213 rtl_tx_performance_tweak(tp->pci_dev,
4214 (0x2 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN);
4215}
4216
4217static void r8168b_0_hw_jumbo_disable(struct rtl8169_private *tp)
4218{
4219 rtl_tx_performance_tweak(tp->pci_dev,
4220 (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN);
4221}
4222
4223static void r8168b_1_hw_jumbo_enable(struct rtl8169_private *tp)
4224{
4225 void __iomem *ioaddr = tp->mmio_addr;
4226
4227 r8168b_0_hw_jumbo_enable(tp);
4228
4229 RTL_W8(Config4, RTL_R8(Config4) | (1 << 0));
4230}
4231
4232static void r8168b_1_hw_jumbo_disable(struct rtl8169_private *tp)
4233{
4234 void __iomem *ioaddr = tp->mmio_addr;
4235
4236 r8168b_0_hw_jumbo_disable(tp);
4237
4238 RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0));
4239}
4240
Bill Pembertonbaf63292012-12-03 09:23:28 -05004241static void rtl_init_jumbo_ops(struct rtl8169_private *tp)
Francois Romieud58d46b2011-05-03 16:38:29 +02004242{
4243 struct jumbo_ops *ops = &tp->jumbo_ops;
4244
4245 switch (tp->mac_version) {
4246 case RTL_GIGA_MAC_VER_11:
4247 ops->disable = r8168b_0_hw_jumbo_disable;
4248 ops->enable = r8168b_0_hw_jumbo_enable;
4249 break;
4250 case RTL_GIGA_MAC_VER_12:
4251 case RTL_GIGA_MAC_VER_17:
4252 ops->disable = r8168b_1_hw_jumbo_disable;
4253 ops->enable = r8168b_1_hw_jumbo_enable;
4254 break;
4255 case RTL_GIGA_MAC_VER_18: /* Wild guess. Needs info from Realtek. */
4256 case RTL_GIGA_MAC_VER_19:
4257 case RTL_GIGA_MAC_VER_20:
4258 case RTL_GIGA_MAC_VER_21: /* Wild guess. Needs info from Realtek. */
4259 case RTL_GIGA_MAC_VER_22:
4260 case RTL_GIGA_MAC_VER_23:
4261 case RTL_GIGA_MAC_VER_24:
4262 case RTL_GIGA_MAC_VER_25:
4263 case RTL_GIGA_MAC_VER_26:
4264 ops->disable = r8168c_hw_jumbo_disable;
4265 ops->enable = r8168c_hw_jumbo_enable;
4266 break;
4267 case RTL_GIGA_MAC_VER_27:
4268 case RTL_GIGA_MAC_VER_28:
4269 ops->disable = r8168dp_hw_jumbo_disable;
4270 ops->enable = r8168dp_hw_jumbo_enable;
4271 break;
4272 case RTL_GIGA_MAC_VER_31: /* Wild guess. Needs info from Realtek. */
4273 case RTL_GIGA_MAC_VER_32:
4274 case RTL_GIGA_MAC_VER_33:
4275 case RTL_GIGA_MAC_VER_34:
4276 ops->disable = r8168e_hw_jumbo_disable;
4277 ops->enable = r8168e_hw_jumbo_enable;
4278 break;
4279
4280 /*
4281 * No action needed for jumbo frames with 8169.
4282 * No jumbo for 810x at all.
4283 */
Hayes Wangc5583862012-07-02 17:23:22 +08004284 case RTL_GIGA_MAC_VER_40:
4285 case RTL_GIGA_MAC_VER_41:
Francois Romieud58d46b2011-05-03 16:38:29 +02004286 default:
4287 ops->disable = NULL;
4288 ops->enable = NULL;
4289 break;
4290 }
4291}
4292
Francois Romieuffc46952012-07-06 14:19:23 +02004293DECLARE_RTL_COND(rtl_chipcmd_cond)
4294{
4295 void __iomem *ioaddr = tp->mmio_addr;
4296
4297 return RTL_R8(ChipCmd) & CmdReset;
4298}
4299
Francois Romieu6f43adc2011-04-29 15:05:51 +02004300static void rtl_hw_reset(struct rtl8169_private *tp)
4301{
4302 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu6f43adc2011-04-29 15:05:51 +02004303
Francois Romieu6f43adc2011-04-29 15:05:51 +02004304 RTL_W8(ChipCmd, CmdReset);
4305
Francois Romieuffc46952012-07-06 14:19:23 +02004306 rtl_udelay_loop_wait_low(tp, &rtl_chipcmd_cond, 100, 100);
Francois Romieu6f43adc2011-04-29 15:05:51 +02004307}
4308
Francois Romieub6ffd972011-06-17 17:00:05 +02004309static void rtl_request_uncached_firmware(struct rtl8169_private *tp)
4310{
4311 struct rtl_fw *rtl_fw;
4312 const char *name;
4313 int rc = -ENOMEM;
4314
4315 name = rtl_lookup_firmware_name(tp);
4316 if (!name)
4317 goto out_no_firmware;
4318
4319 rtl_fw = kzalloc(sizeof(*rtl_fw), GFP_KERNEL);
4320 if (!rtl_fw)
4321 goto err_warn;
4322
4323 rc = request_firmware(&rtl_fw->fw, name, &tp->pci_dev->dev);
4324 if (rc < 0)
4325 goto err_free;
4326
Francois Romieufd112f22011-06-18 00:10:29 +02004327 rc = rtl_check_firmware(tp, rtl_fw);
4328 if (rc < 0)
4329 goto err_release_firmware;
4330
Francois Romieub6ffd972011-06-17 17:00:05 +02004331 tp->rtl_fw = rtl_fw;
4332out:
4333 return;
4334
Francois Romieufd112f22011-06-18 00:10:29 +02004335err_release_firmware:
4336 release_firmware(rtl_fw->fw);
Francois Romieub6ffd972011-06-17 17:00:05 +02004337err_free:
4338 kfree(rtl_fw);
4339err_warn:
4340 netif_warn(tp, ifup, tp->dev, "unable to load firmware patch %s (%d)\n",
4341 name, rc);
4342out_no_firmware:
4343 tp->rtl_fw = NULL;
4344 goto out;
4345}
4346
François Romieu953a12c2011-04-24 17:38:48 +02004347static void rtl_request_firmware(struct rtl8169_private *tp)
4348{
Francois Romieub6ffd972011-06-17 17:00:05 +02004349 if (IS_ERR(tp->rtl_fw))
4350 rtl_request_uncached_firmware(tp);
François Romieu953a12c2011-04-24 17:38:48 +02004351}
4352
Hayes Wang92fc43b2011-07-06 15:58:03 +08004353static void rtl_rx_close(struct rtl8169_private *tp)
4354{
4355 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang92fc43b2011-07-06 15:58:03 +08004356
Francois Romieu1687b562011-07-19 17:21:29 +02004357 RTL_W32(RxConfig, RTL_R32(RxConfig) & ~RX_CONFIG_ACCEPT_MASK);
Hayes Wang92fc43b2011-07-06 15:58:03 +08004358}
4359
Francois Romieuffc46952012-07-06 14:19:23 +02004360DECLARE_RTL_COND(rtl_npq_cond)
4361{
4362 void __iomem *ioaddr = tp->mmio_addr;
4363
4364 return RTL_R8(TxPoll) & NPQ;
4365}
4366
4367DECLARE_RTL_COND(rtl_txcfg_empty_cond)
4368{
4369 void __iomem *ioaddr = tp->mmio_addr;
4370
4371 return RTL_R32(TxConfig) & TXCFG_EMPTY;
4372}
4373
françois romieue6de30d2011-01-03 15:08:37 +00004374static void rtl8169_hw_reset(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004375{
françois romieue6de30d2011-01-03 15:08:37 +00004376 void __iomem *ioaddr = tp->mmio_addr;
4377
Linus Torvalds1da177e2005-04-16 15:20:36 -07004378 /* Disable interrupts */
françois romieu811fd302011-12-04 20:30:45 +00004379 rtl8169_irq_mask_and_ack(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004380
Hayes Wang92fc43b2011-07-06 15:58:03 +08004381 rtl_rx_close(tp);
4382
Hayes Wang5d2e1952011-02-22 17:26:22 +08004383 if (tp->mac_version == RTL_GIGA_MAC_VER_27 ||
hayeswang4804b3b2011-03-21 01:50:29 +00004384 tp->mac_version == RTL_GIGA_MAC_VER_28 ||
4385 tp->mac_version == RTL_GIGA_MAC_VER_31) {
Francois Romieuffc46952012-07-06 14:19:23 +02004386 rtl_udelay_loop_wait_low(tp, &rtl_npq_cond, 20, 42*42);
Hayes Wangc2218922011-09-06 16:55:18 +08004387 } else if (tp->mac_version == RTL_GIGA_MAC_VER_34 ||
4388 tp->mac_version == RTL_GIGA_MAC_VER_35 ||
Hayes Wang7e18dca2012-03-30 14:33:02 +08004389 tp->mac_version == RTL_GIGA_MAC_VER_36 ||
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08004390 tp->mac_version == RTL_GIGA_MAC_VER_37 ||
Hayes Wangc5583862012-07-02 17:23:22 +08004391 tp->mac_version == RTL_GIGA_MAC_VER_40 ||
4392 tp->mac_version == RTL_GIGA_MAC_VER_41 ||
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08004393 tp->mac_version == RTL_GIGA_MAC_VER_38) {
David S. Miller8decf862011-09-22 03:23:13 -04004394 RTL_W8(ChipCmd, RTL_R8(ChipCmd) | StopReq);
Francois Romieuffc46952012-07-06 14:19:23 +02004395 rtl_udelay_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 666);
Hayes Wang92fc43b2011-07-06 15:58:03 +08004396 } else {
4397 RTL_W8(ChipCmd, RTL_R8(ChipCmd) | StopReq);
4398 udelay(100);
françois romieue6de30d2011-01-03 15:08:37 +00004399 }
4400
Hayes Wang92fc43b2011-07-06 15:58:03 +08004401 rtl_hw_reset(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004402}
4403
Francois Romieu7f796d832007-06-11 23:04:41 +02004404static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp)
Francois Romieu9cb427b2006-11-02 00:10:16 +01004405{
4406 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu9cb427b2006-11-02 00:10:16 +01004407
4408 /* Set DMA burst size and Interframe Gap Time */
4409 RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) |
4410 (InterFrameGap << TxInterFrameGapShift));
4411}
4412
Francois Romieu07ce4062007-02-23 23:36:39 +01004413static void rtl_hw_start(struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004414{
4415 struct rtl8169_private *tp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004416
Francois Romieu07ce4062007-02-23 23:36:39 +01004417 tp->hw_start(dev);
4418
Francois Romieuda78dbf2012-01-26 14:18:23 +01004419 rtl_irq_enable_all(tp);
Francois Romieu07ce4062007-02-23 23:36:39 +01004420}
4421
Francois Romieu7f796d832007-06-11 23:04:41 +02004422static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp,
4423 void __iomem *ioaddr)
4424{
4425 /*
4426 * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh
4427 * register to be written before TxDescAddrLow to work.
4428 * Switching from MMIO to I/O access fixes the issue as well.
4429 */
4430 RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr) >> 32);
Yang Hongyang284901a2009-04-06 19:01:15 -07004431 RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr) & DMA_BIT_MASK(32));
Francois Romieu7f796d832007-06-11 23:04:41 +02004432 RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32);
Yang Hongyang284901a2009-04-06 19:01:15 -07004433 RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_BIT_MASK(32));
Francois Romieu7f796d832007-06-11 23:04:41 +02004434}
4435
4436static u16 rtl_rw_cpluscmd(void __iomem *ioaddr)
4437{
4438 u16 cmd;
4439
4440 cmd = RTL_R16(CPlusCmd);
4441 RTL_W16(CPlusCmd, cmd);
4442 return cmd;
4443}
4444
Eric Dumazetfdd7b4c2009-06-09 04:01:02 -07004445static void rtl_set_rx_max_size(void __iomem *ioaddr, unsigned int rx_buf_sz)
Francois Romieu7f796d832007-06-11 23:04:41 +02004446{
4447 /* Low hurts. Let's disable the filtering. */
Raimonds Cicans207d6e872009-10-26 10:52:37 +00004448 RTL_W16(RxMaxSize, rx_buf_sz + 1);
Francois Romieu7f796d832007-06-11 23:04:41 +02004449}
4450
Francois Romieu6dccd162007-02-13 23:38:05 +01004451static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version)
4452{
Francois Romieu37441002011-06-17 22:58:54 +02004453 static const struct rtl_cfg2_info {
Francois Romieu6dccd162007-02-13 23:38:05 +01004454 u32 mac_version;
4455 u32 clk;
4456 u32 val;
4457 } cfg2_info [] = {
4458 { RTL_GIGA_MAC_VER_05, PCI_Clock_33MHz, 0x000fff00 }, // 8110SCd
4459 { RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff },
4460 { RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe
4461 { RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff }
Francois Romieu37441002011-06-17 22:58:54 +02004462 };
4463 const struct rtl_cfg2_info *p = cfg2_info;
Francois Romieu6dccd162007-02-13 23:38:05 +01004464 unsigned int i;
4465 u32 clk;
4466
4467 clk = RTL_R8(Config2) & PCI_Clock_66MHz;
Francois Romieucadf1852008-01-03 23:38:38 +01004468 for (i = 0; i < ARRAY_SIZE(cfg2_info); i++, p++) {
Francois Romieu6dccd162007-02-13 23:38:05 +01004469 if ((p->mac_version == mac_version) && (p->clk == clk)) {
4470 RTL_W32(0x7c, p->val);
4471 break;
4472 }
4473 }
4474}
4475
Francois Romieue6b763e2012-03-08 09:35:39 +01004476static void rtl_set_rx_mode(struct net_device *dev)
4477{
4478 struct rtl8169_private *tp = netdev_priv(dev);
4479 void __iomem *ioaddr = tp->mmio_addr;
4480 u32 mc_filter[2]; /* Multicast hash filter */
4481 int rx_mode;
4482 u32 tmp = 0;
4483
4484 if (dev->flags & IFF_PROMISC) {
4485 /* Unconditionally log net taps. */
4486 netif_notice(tp, link, dev, "Promiscuous mode enabled\n");
4487 rx_mode =
4488 AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
4489 AcceptAllPhys;
4490 mc_filter[1] = mc_filter[0] = 0xffffffff;
4491 } else if ((netdev_mc_count(dev) > multicast_filter_limit) ||
4492 (dev->flags & IFF_ALLMULTI)) {
4493 /* Too many to filter perfectly -- accept all multicasts. */
4494 rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
4495 mc_filter[1] = mc_filter[0] = 0xffffffff;
4496 } else {
4497 struct netdev_hw_addr *ha;
4498
4499 rx_mode = AcceptBroadcast | AcceptMyPhys;
4500 mc_filter[1] = mc_filter[0] = 0;
4501 netdev_for_each_mc_addr(ha, dev) {
4502 int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26;
4503 mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
4504 rx_mode |= AcceptMulticast;
4505 }
4506 }
4507
4508 if (dev->features & NETIF_F_RXALL)
4509 rx_mode |= (AcceptErr | AcceptRunt);
4510
4511 tmp = (RTL_R32(RxConfig) & ~RX_CONFIG_ACCEPT_MASK) | rx_mode;
4512
4513 if (tp->mac_version > RTL_GIGA_MAC_VER_06) {
4514 u32 data = mc_filter[0];
4515
4516 mc_filter[0] = swab32(mc_filter[1]);
4517 mc_filter[1] = swab32(data);
4518 }
4519
Nathan Walp04817762012-11-01 12:08:47 +00004520 if (tp->mac_version == RTL_GIGA_MAC_VER_35)
4521 mc_filter[1] = mc_filter[0] = 0xffffffff;
4522
Francois Romieue6b763e2012-03-08 09:35:39 +01004523 RTL_W32(MAR0 + 4, mc_filter[1]);
4524 RTL_W32(MAR0 + 0, mc_filter[0]);
4525
4526 RTL_W32(RxConfig, tmp);
4527}
4528
Francois Romieu07ce4062007-02-23 23:36:39 +01004529static void rtl_hw_start_8169(struct net_device *dev)
4530{
4531 struct rtl8169_private *tp = netdev_priv(dev);
4532 void __iomem *ioaddr = tp->mmio_addr;
4533 struct pci_dev *pdev = tp->pci_dev;
Francois Romieu07ce4062007-02-23 23:36:39 +01004534
Francois Romieu9cb427b2006-11-02 00:10:16 +01004535 if (tp->mac_version == RTL_GIGA_MAC_VER_05) {
4536 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW);
4537 pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08);
4538 }
4539
Linus Torvalds1da177e2005-04-16 15:20:36 -07004540 RTL_W8(Cfg9346, Cfg9346_Unlock);
Francois Romieucecb5fd2011-04-01 10:21:07 +02004541 if (tp->mac_version == RTL_GIGA_MAC_VER_01 ||
4542 tp->mac_version == RTL_GIGA_MAC_VER_02 ||
4543 tp->mac_version == RTL_GIGA_MAC_VER_03 ||
4544 tp->mac_version == RTL_GIGA_MAC_VER_04)
Francois Romieu9cb427b2006-11-02 00:10:16 +01004545 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
4546
Hayes Wange542a222011-07-06 15:58:04 +08004547 rtl_init_rxcfg(tp);
4548
françois romieuf0298f82011-01-03 15:07:42 +00004549 RTL_W8(EarlyTxThres, NoEarlyTx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004550
Eric Dumazet6f0333b2010-10-11 11:17:47 +00004551 rtl_set_rx_max_size(ioaddr, rx_buf_sz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004552
Francois Romieucecb5fd2011-04-01 10:21:07 +02004553 if (tp->mac_version == RTL_GIGA_MAC_VER_01 ||
4554 tp->mac_version == RTL_GIGA_MAC_VER_02 ||
4555 tp->mac_version == RTL_GIGA_MAC_VER_03 ||
4556 tp->mac_version == RTL_GIGA_MAC_VER_04)
Francois Romieuc946b302007-10-04 00:42:50 +02004557 rtl_set_rx_tx_config_registers(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004558
Francois Romieu7f796d832007-06-11 23:04:41 +02004559 tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW;
Francois Romieubcf0bf92006-07-26 23:14:13 +02004560
Francois Romieucecb5fd2011-04-01 10:21:07 +02004561 if (tp->mac_version == RTL_GIGA_MAC_VER_02 ||
4562 tp->mac_version == RTL_GIGA_MAC_VER_03) {
Joe Perches06fa7352007-10-18 21:15:00 +02004563 dprintk("Set MAC Reg C+CR Offset 0xE0. "
Linus Torvalds1da177e2005-04-16 15:20:36 -07004564 "Bit-3 and bit-14 MUST be 1\n");
Francois Romieubcf0bf92006-07-26 23:14:13 +02004565 tp->cp_cmd |= (1 << 14);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004566 }
4567
Francois Romieubcf0bf92006-07-26 23:14:13 +02004568 RTL_W16(CPlusCmd, tp->cp_cmd);
4569
Francois Romieu6dccd162007-02-13 23:38:05 +01004570 rtl8169_set_magic_reg(ioaddr, tp->mac_version);
4571
Linus Torvalds1da177e2005-04-16 15:20:36 -07004572 /*
4573 * Undocumented corner. Supposedly:
4574 * (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets
4575 */
4576 RTL_W16(IntrMitigate, 0x0000);
4577
Francois Romieu7f796d832007-06-11 23:04:41 +02004578 rtl_set_rx_tx_desc_registers(tp, ioaddr);
Francois Romieu9cb427b2006-11-02 00:10:16 +01004579
Francois Romieucecb5fd2011-04-01 10:21:07 +02004580 if (tp->mac_version != RTL_GIGA_MAC_VER_01 &&
4581 tp->mac_version != RTL_GIGA_MAC_VER_02 &&
4582 tp->mac_version != RTL_GIGA_MAC_VER_03 &&
4583 tp->mac_version != RTL_GIGA_MAC_VER_04) {
Francois Romieuc946b302007-10-04 00:42:50 +02004584 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
4585 rtl_set_rx_tx_config_registers(tp);
4586 }
4587
Linus Torvalds1da177e2005-04-16 15:20:36 -07004588 RTL_W8(Cfg9346, Cfg9346_Lock);
Francois Romieub518fa82006-08-16 15:23:13 +02004589
4590 /* Initially a 10 us delay. Turned it into a PCI commit. - FR */
4591 RTL_R8(IntrMask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004592
4593 RTL_W32(RxMissed, 0);
4594
Francois Romieu07ce4062007-02-23 23:36:39 +01004595 rtl_set_rx_mode(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004596
4597 /* no early-rx interrupts */
4598 RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000);
Francois Romieu07ce4062007-02-23 23:36:39 +01004599}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004600
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004601static void rtl_csi_write(struct rtl8169_private *tp, int addr, int value)
4602{
4603 if (tp->csi_ops.write)
Francois Romieu52989f02012-07-06 13:37:00 +02004604 tp->csi_ops.write(tp, addr, value);
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004605}
4606
4607static u32 rtl_csi_read(struct rtl8169_private *tp, int addr)
4608{
Francois Romieu52989f02012-07-06 13:37:00 +02004609 return tp->csi_ops.read ? tp->csi_ops.read(tp, addr) : ~0;
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004610}
4611
4612static void rtl_csi_access_enable(struct rtl8169_private *tp, u32 bits)
Francois Romieudacf8152008-08-02 20:44:13 +02004613{
4614 u32 csi;
4615
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004616 csi = rtl_csi_read(tp, 0x070c) & 0x00ffffff;
4617 rtl_csi_write(tp, 0x070c, csi | bits);
françois romieu650e8d52011-01-03 15:08:29 +00004618}
4619
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004620static void rtl_csi_access_enable_1(struct rtl8169_private *tp)
françois romieue6de30d2011-01-03 15:08:37 +00004621{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004622 rtl_csi_access_enable(tp, 0x17000000);
françois romieue6de30d2011-01-03 15:08:37 +00004623}
4624
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004625static void rtl_csi_access_enable_2(struct rtl8169_private *tp)
françois romieu650e8d52011-01-03 15:08:29 +00004626{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004627 rtl_csi_access_enable(tp, 0x27000000);
4628}
4629
Francois Romieuffc46952012-07-06 14:19:23 +02004630DECLARE_RTL_COND(rtl_csiar_cond)
4631{
4632 void __iomem *ioaddr = tp->mmio_addr;
4633
4634 return RTL_R32(CSIAR) & CSIAR_FLAG;
4635}
4636
Francois Romieu52989f02012-07-06 13:37:00 +02004637static void r8169_csi_write(struct rtl8169_private *tp, int addr, int value)
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004638{
Francois Romieu52989f02012-07-06 13:37:00 +02004639 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004640
4641 RTL_W32(CSIDR, value);
4642 RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) |
4643 CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT);
4644
Francois Romieuffc46952012-07-06 14:19:23 +02004645 rtl_udelay_loop_wait_low(tp, &rtl_csiar_cond, 10, 100);
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004646}
4647
Francois Romieu52989f02012-07-06 13:37:00 +02004648static u32 r8169_csi_read(struct rtl8169_private *tp, int addr)
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004649{
Francois Romieu52989f02012-07-06 13:37:00 +02004650 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004651
4652 RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) |
4653 CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT);
4654
Francois Romieuffc46952012-07-06 14:19:23 +02004655 return rtl_udelay_loop_wait_high(tp, &rtl_csiar_cond, 10, 100) ?
4656 RTL_R32(CSIDR) : ~0;
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004657}
4658
Francois Romieu52989f02012-07-06 13:37:00 +02004659static void r8402_csi_write(struct rtl8169_private *tp, int addr, int value)
Hayes Wang7e18dca2012-03-30 14:33:02 +08004660{
Francois Romieu52989f02012-07-06 13:37:00 +02004661 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang7e18dca2012-03-30 14:33:02 +08004662
4663 RTL_W32(CSIDR, value);
4664 RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) |
4665 CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT |
4666 CSIAR_FUNC_NIC);
4667
Francois Romieuffc46952012-07-06 14:19:23 +02004668 rtl_udelay_loop_wait_low(tp, &rtl_csiar_cond, 10, 100);
Hayes Wang7e18dca2012-03-30 14:33:02 +08004669}
4670
Francois Romieu52989f02012-07-06 13:37:00 +02004671static u32 r8402_csi_read(struct rtl8169_private *tp, int addr)
Hayes Wang7e18dca2012-03-30 14:33:02 +08004672{
Francois Romieu52989f02012-07-06 13:37:00 +02004673 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang7e18dca2012-03-30 14:33:02 +08004674
4675 RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) | CSIAR_FUNC_NIC |
4676 CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT);
4677
Francois Romieuffc46952012-07-06 14:19:23 +02004678 return rtl_udelay_loop_wait_high(tp, &rtl_csiar_cond, 10, 100) ?
4679 RTL_R32(CSIDR) : ~0;
Hayes Wang7e18dca2012-03-30 14:33:02 +08004680}
4681
Bill Pembertonbaf63292012-12-03 09:23:28 -05004682static void rtl_init_csi_ops(struct rtl8169_private *tp)
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004683{
4684 struct csi_ops *ops = &tp->csi_ops;
4685
4686 switch (tp->mac_version) {
4687 case RTL_GIGA_MAC_VER_01:
4688 case RTL_GIGA_MAC_VER_02:
4689 case RTL_GIGA_MAC_VER_03:
4690 case RTL_GIGA_MAC_VER_04:
4691 case RTL_GIGA_MAC_VER_05:
4692 case RTL_GIGA_MAC_VER_06:
4693 case RTL_GIGA_MAC_VER_10:
4694 case RTL_GIGA_MAC_VER_11:
4695 case RTL_GIGA_MAC_VER_12:
4696 case RTL_GIGA_MAC_VER_13:
4697 case RTL_GIGA_MAC_VER_14:
4698 case RTL_GIGA_MAC_VER_15:
4699 case RTL_GIGA_MAC_VER_16:
4700 case RTL_GIGA_MAC_VER_17:
4701 ops->write = NULL;
4702 ops->read = NULL;
4703 break;
4704
Hayes Wang7e18dca2012-03-30 14:33:02 +08004705 case RTL_GIGA_MAC_VER_37:
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08004706 case RTL_GIGA_MAC_VER_38:
Hayes Wang7e18dca2012-03-30 14:33:02 +08004707 ops->write = r8402_csi_write;
4708 ops->read = r8402_csi_read;
4709 break;
4710
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004711 default:
4712 ops->write = r8169_csi_write;
4713 ops->read = r8169_csi_read;
4714 break;
4715 }
Francois Romieudacf8152008-08-02 20:44:13 +02004716}
4717
4718struct ephy_info {
4719 unsigned int offset;
4720 u16 mask;
4721 u16 bits;
4722};
4723
Francois Romieufdf6fc02012-07-06 22:40:38 +02004724static void rtl_ephy_init(struct rtl8169_private *tp, const struct ephy_info *e,
4725 int len)
Francois Romieudacf8152008-08-02 20:44:13 +02004726{
4727 u16 w;
4728
4729 while (len-- > 0) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02004730 w = (rtl_ephy_read(tp, e->offset) & ~e->mask) | e->bits;
4731 rtl_ephy_write(tp, e->offset, w);
Francois Romieudacf8152008-08-02 20:44:13 +02004732 e++;
4733 }
4734}
4735
Francois Romieub726e492008-06-28 12:22:59 +02004736static void rtl_disable_clock_request(struct pci_dev *pdev)
4737{
Jiang Liu7d7903b2012-07-24 17:20:16 +08004738 pcie_capability_clear_word(pdev, PCI_EXP_LNKCTL,
4739 PCI_EXP_LNKCTL_CLKREQ_EN);
Francois Romieub726e492008-06-28 12:22:59 +02004740}
4741
françois romieue6de30d2011-01-03 15:08:37 +00004742static void rtl_enable_clock_request(struct pci_dev *pdev)
4743{
Jiang Liu7d7903b2012-07-24 17:20:16 +08004744 pcie_capability_set_word(pdev, PCI_EXP_LNKCTL,
4745 PCI_EXP_LNKCTL_CLKREQ_EN);
françois romieue6de30d2011-01-03 15:08:37 +00004746}
4747
Francois Romieub726e492008-06-28 12:22:59 +02004748#define R8168_CPCMD_QUIRK_MASK (\
4749 EnableBist | \
4750 Mac_dbgo_oe | \
4751 Force_half_dup | \
4752 Force_rxflow_en | \
4753 Force_txflow_en | \
4754 Cxpl_dbg_sel | \
4755 ASF | \
4756 PktCntrDisable | \
4757 Mac_dbgo_sel)
4758
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004759static void rtl_hw_start_8168bb(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004760{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004761 void __iomem *ioaddr = tp->mmio_addr;
4762 struct pci_dev *pdev = tp->pci_dev;
4763
Francois Romieub726e492008-06-28 12:22:59 +02004764 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
4765
4766 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
4767
françois romieufaf1e782013-02-27 13:01:57 +00004768 if (tp->dev->mtu <= ETH_DATA_LEN) {
4769 rtl_tx_performance_tweak(pdev, (0x5 << MAX_READ_REQUEST_SHIFT) |
4770 PCI_EXP_DEVCTL_NOSNOOP_EN);
4771 }
Francois Romieu219a1e92008-06-28 11:58:39 +02004772}
4773
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004774static void rtl_hw_start_8168bef(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004775{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004776 void __iomem *ioaddr = tp->mmio_addr;
4777
4778 rtl_hw_start_8168bb(tp);
Francois Romieub726e492008-06-28 12:22:59 +02004779
françois romieuf0298f82011-01-03 15:07:42 +00004780 RTL_W8(MaxTxPacketSize, TxPacketMax);
Francois Romieub726e492008-06-28 12:22:59 +02004781
4782 RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0));
Francois Romieu219a1e92008-06-28 11:58:39 +02004783}
4784
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004785static void __rtl_hw_start_8168cp(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004786{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004787 void __iomem *ioaddr = tp->mmio_addr;
4788 struct pci_dev *pdev = tp->pci_dev;
4789
Francois Romieub726e492008-06-28 12:22:59 +02004790 RTL_W8(Config1, RTL_R8(Config1) | Speed_down);
4791
4792 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
4793
françois romieufaf1e782013-02-27 13:01:57 +00004794 if (tp->dev->mtu <= ETH_DATA_LEN)
4795 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
Francois Romieub726e492008-06-28 12:22:59 +02004796
4797 rtl_disable_clock_request(pdev);
4798
4799 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
Francois Romieu219a1e92008-06-28 11:58:39 +02004800}
4801
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004802static void rtl_hw_start_8168cp_1(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004803{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08004804 static const struct ephy_info e_info_8168cp[] = {
Francois Romieub726e492008-06-28 12:22:59 +02004805 { 0x01, 0, 0x0001 },
4806 { 0x02, 0x0800, 0x1000 },
4807 { 0x03, 0, 0x0042 },
4808 { 0x06, 0x0080, 0x0000 },
4809 { 0x07, 0, 0x2000 }
4810 };
4811
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004812 rtl_csi_access_enable_2(tp);
Francois Romieub726e492008-06-28 12:22:59 +02004813
Francois Romieufdf6fc02012-07-06 22:40:38 +02004814 rtl_ephy_init(tp, e_info_8168cp, ARRAY_SIZE(e_info_8168cp));
Francois Romieub726e492008-06-28 12:22:59 +02004815
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004816 __rtl_hw_start_8168cp(tp);
Francois Romieu219a1e92008-06-28 11:58:39 +02004817}
4818
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004819static void rtl_hw_start_8168cp_2(struct rtl8169_private *tp)
Francois Romieuef3386f2008-06-29 12:24:30 +02004820{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004821 void __iomem *ioaddr = tp->mmio_addr;
4822 struct pci_dev *pdev = tp->pci_dev;
4823
4824 rtl_csi_access_enable_2(tp);
Francois Romieuef3386f2008-06-29 12:24:30 +02004825
4826 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
4827
françois romieufaf1e782013-02-27 13:01:57 +00004828 if (tp->dev->mtu <= ETH_DATA_LEN)
4829 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
Francois Romieuef3386f2008-06-29 12:24:30 +02004830
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
françois romieufaf1e782013-02-27 13:01:57 +00004848 if (tp->dev->mtu <= ETH_DATA_LEN)
4849 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
Francois Romieu7f3e3d32008-07-20 18:53:20 +02004850
4851 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
4852}
4853
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004854static void rtl_hw_start_8168c_1(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004855{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004856 void __iomem *ioaddr = tp->mmio_addr;
Alexey Dobriyan350f7592009-11-25 15:54:21 -08004857 static const struct ephy_info e_info_8168c_1[] = {
Francois Romieub726e492008-06-28 12:22:59 +02004858 { 0x02, 0x0800, 0x1000 },
4859 { 0x03, 0, 0x0002 },
4860 { 0x06, 0x0080, 0x0000 }
4861 };
4862
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004863 rtl_csi_access_enable_2(tp);
Francois Romieub726e492008-06-28 12:22:59 +02004864
4865 RTL_W8(DBG_REG, 0x06 | FIX_NAK_1 | FIX_NAK_2);
4866
Francois Romieufdf6fc02012-07-06 22:40:38 +02004867 rtl_ephy_init(tp, e_info_8168c_1, ARRAY_SIZE(e_info_8168c_1));
Francois Romieub726e492008-06-28 12:22:59 +02004868
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004869 __rtl_hw_start_8168cp(tp);
Francois Romieu219a1e92008-06-28 11:58:39 +02004870}
4871
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004872static void rtl_hw_start_8168c_2(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004873{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08004874 static const struct ephy_info e_info_8168c_2[] = {
Francois Romieub726e492008-06-28 12:22:59 +02004875 { 0x01, 0, 0x0001 },
4876 { 0x03, 0x0400, 0x0220 }
4877 };
4878
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004879 rtl_csi_access_enable_2(tp);
Francois Romieub726e492008-06-28 12:22:59 +02004880
Francois Romieufdf6fc02012-07-06 22:40:38 +02004881 rtl_ephy_init(tp, e_info_8168c_2, ARRAY_SIZE(e_info_8168c_2));
Francois Romieub726e492008-06-28 12:22:59 +02004882
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004883 __rtl_hw_start_8168cp(tp);
Francois Romieu219a1e92008-06-28 11:58:39 +02004884}
4885
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004886static void rtl_hw_start_8168c_3(struct rtl8169_private *tp)
Francois Romieu197ff762008-06-28 13:16:02 +02004887{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004888 rtl_hw_start_8168c_2(tp);
Francois Romieu197ff762008-06-28 13:16:02 +02004889}
4890
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004891static void rtl_hw_start_8168c_4(struct rtl8169_private *tp)
Francois Romieu6fb07052008-06-29 11:54:28 +02004892{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004893 rtl_csi_access_enable_2(tp);
Francois Romieu6fb07052008-06-29 11:54:28 +02004894
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004895 __rtl_hw_start_8168cp(tp);
Francois Romieu6fb07052008-06-29 11:54:28 +02004896}
4897
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004898static void rtl_hw_start_8168d(struct rtl8169_private *tp)
Francois Romieu5b538df2008-07-20 16:22:45 +02004899{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004900 void __iomem *ioaddr = tp->mmio_addr;
4901 struct pci_dev *pdev = tp->pci_dev;
4902
4903 rtl_csi_access_enable_2(tp);
Francois Romieu5b538df2008-07-20 16:22:45 +02004904
4905 rtl_disable_clock_request(pdev);
4906
françois romieuf0298f82011-01-03 15:07:42 +00004907 RTL_W8(MaxTxPacketSize, TxPacketMax);
Francois Romieu5b538df2008-07-20 16:22:45 +02004908
françois romieufaf1e782013-02-27 13:01:57 +00004909 if (tp->dev->mtu <= ETH_DATA_LEN)
4910 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
Francois Romieu5b538df2008-07-20 16:22:45 +02004911
4912 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
4913}
4914
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004915static void rtl_hw_start_8168dp(struct rtl8169_private *tp)
hayeswang4804b3b2011-03-21 01:50:29 +00004916{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004917 void __iomem *ioaddr = tp->mmio_addr;
4918 struct pci_dev *pdev = tp->pci_dev;
4919
4920 rtl_csi_access_enable_1(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00004921
françois romieufaf1e782013-02-27 13:01:57 +00004922 if (tp->dev->mtu <= ETH_DATA_LEN)
4923 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
hayeswang4804b3b2011-03-21 01:50:29 +00004924
4925 RTL_W8(MaxTxPacketSize, TxPacketMax);
4926
4927 rtl_disable_clock_request(pdev);
4928}
4929
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004930static void rtl_hw_start_8168d_4(struct rtl8169_private *tp)
françois romieue6de30d2011-01-03 15:08:37 +00004931{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004932 void __iomem *ioaddr = tp->mmio_addr;
4933 struct pci_dev *pdev = tp->pci_dev;
françois romieue6de30d2011-01-03 15:08:37 +00004934 static const struct ephy_info e_info_8168d_4[] = {
4935 { 0x0b, ~0, 0x48 },
4936 { 0x19, 0x20, 0x50 },
4937 { 0x0c, ~0, 0x20 }
4938 };
4939 int i;
4940
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004941 rtl_csi_access_enable_1(tp);
françois romieue6de30d2011-01-03 15:08:37 +00004942
4943 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
4944
4945 RTL_W8(MaxTxPacketSize, TxPacketMax);
4946
4947 for (i = 0; i < ARRAY_SIZE(e_info_8168d_4); i++) {
4948 const struct ephy_info *e = e_info_8168d_4 + i;
4949 u16 w;
4950
Francois Romieufdf6fc02012-07-06 22:40:38 +02004951 w = rtl_ephy_read(tp, e->offset);
4952 rtl_ephy_write(tp, 0x03, (w & e->mask) | e->bits);
françois romieue6de30d2011-01-03 15:08:37 +00004953 }
4954
4955 rtl_enable_clock_request(pdev);
4956}
4957
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004958static void rtl_hw_start_8168e_1(struct rtl8169_private *tp)
hayeswang01dc7fe2011-03-21 01:50:28 +00004959{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004960 void __iomem *ioaddr = tp->mmio_addr;
4961 struct pci_dev *pdev = tp->pci_dev;
Hayes Wang70090422011-07-06 15:58:06 +08004962 static const struct ephy_info e_info_8168e_1[] = {
hayeswang01dc7fe2011-03-21 01:50:28 +00004963 { 0x00, 0x0200, 0x0100 },
4964 { 0x00, 0x0000, 0x0004 },
4965 { 0x06, 0x0002, 0x0001 },
4966 { 0x06, 0x0000, 0x0030 },
4967 { 0x07, 0x0000, 0x2000 },
4968 { 0x00, 0x0000, 0x0020 },
4969 { 0x03, 0x5800, 0x2000 },
4970 { 0x03, 0x0000, 0x0001 },
4971 { 0x01, 0x0800, 0x1000 },
4972 { 0x07, 0x0000, 0x4000 },
4973 { 0x1e, 0x0000, 0x2000 },
4974 { 0x19, 0xffff, 0xfe6c },
4975 { 0x0a, 0x0000, 0x0040 }
4976 };
4977
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004978 rtl_csi_access_enable_2(tp);
hayeswang01dc7fe2011-03-21 01:50:28 +00004979
Francois Romieufdf6fc02012-07-06 22:40:38 +02004980 rtl_ephy_init(tp, e_info_8168e_1, ARRAY_SIZE(e_info_8168e_1));
hayeswang01dc7fe2011-03-21 01:50:28 +00004981
françois romieufaf1e782013-02-27 13:01:57 +00004982 if (tp->dev->mtu <= ETH_DATA_LEN)
4983 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
hayeswang01dc7fe2011-03-21 01:50:28 +00004984
4985 RTL_W8(MaxTxPacketSize, TxPacketMax);
4986
4987 rtl_disable_clock_request(pdev);
4988
4989 /* Reset tx FIFO pointer */
Francois Romieucecb5fd2011-04-01 10:21:07 +02004990 RTL_W32(MISC, RTL_R32(MISC) | TXPLA_RST);
4991 RTL_W32(MISC, RTL_R32(MISC) & ~TXPLA_RST);
hayeswang01dc7fe2011-03-21 01:50:28 +00004992
Francois Romieucecb5fd2011-04-01 10:21:07 +02004993 RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en);
hayeswang01dc7fe2011-03-21 01:50:28 +00004994}
4995
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004996static void rtl_hw_start_8168e_2(struct rtl8169_private *tp)
Hayes Wang70090422011-07-06 15:58:06 +08004997{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004998 void __iomem *ioaddr = tp->mmio_addr;
4999 struct pci_dev *pdev = tp->pci_dev;
Hayes Wang70090422011-07-06 15:58:06 +08005000 static const struct ephy_info e_info_8168e_2[] = {
5001 { 0x09, 0x0000, 0x0080 },
5002 { 0x19, 0x0000, 0x0224 }
5003 };
5004
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005005 rtl_csi_access_enable_1(tp);
Hayes Wang70090422011-07-06 15:58:06 +08005006
Francois Romieufdf6fc02012-07-06 22:40:38 +02005007 rtl_ephy_init(tp, e_info_8168e_2, ARRAY_SIZE(e_info_8168e_2));
Hayes Wang70090422011-07-06 15:58:06 +08005008
françois romieufaf1e782013-02-27 13:01:57 +00005009 if (tp->dev->mtu <= ETH_DATA_LEN)
5010 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
Hayes Wang70090422011-07-06 15:58:06 +08005011
Francois Romieufdf6fc02012-07-06 22:40:38 +02005012 rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5013 rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5014 rtl_eri_write(tp, 0xc8, ERIAR_MASK_1111, 0x00100002, ERIAR_EXGMAC);
5015 rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC);
5016 rtl_eri_write(tp, 0xcc, ERIAR_MASK_1111, 0x00000050, ERIAR_EXGMAC);
5017 rtl_eri_write(tp, 0xd0, ERIAR_MASK_1111, 0x07ff0060, ERIAR_EXGMAC);
5018 rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC);
5019 rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0xff00, ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08005020
Hayes Wang3090bd92011-09-06 16:55:15 +08005021 RTL_W8(MaxTxPacketSize, EarlySize);
Hayes Wang70090422011-07-06 15:58:06 +08005022
Francois Romieu4521e1a92012-11-01 16:46:28 +00005023 rtl_disable_clock_request(pdev);
5024
Hayes Wang70090422011-07-06 15:58:06 +08005025 RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
5026 RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
5027
5028 /* Adjust EEE LED frequency */
5029 RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07);
5030
5031 RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
5032 RTL_W32(MISC, RTL_R32(MISC) | PWM_EN);
Francois Romieu4521e1a92012-11-01 16:46:28 +00005033 RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en);
Hayes Wang70090422011-07-06 15:58:06 +08005034}
5035
Hayes Wang5f886e02012-03-30 14:33:03 +08005036static void rtl_hw_start_8168f(struct rtl8169_private *tp)
Hayes Wangc2218922011-09-06 16:55:18 +08005037{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005038 void __iomem *ioaddr = tp->mmio_addr;
5039 struct pci_dev *pdev = tp->pci_dev;
Hayes Wangc2218922011-09-06 16:55:18 +08005040
Hayes Wang5f886e02012-03-30 14:33:03 +08005041 rtl_csi_access_enable_2(tp);
Hayes Wangc2218922011-09-06 16:55:18 +08005042
5043 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5044
Francois Romieufdf6fc02012-07-06 22:40:38 +02005045 rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5046 rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5047 rtl_eri_write(tp, 0xc8, ERIAR_MASK_1111, 0x00100002, ERIAR_EXGMAC);
5048 rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC);
5049 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC);
5050 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC);
5051 rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC);
5052 rtl_w1w0_eri(tp, 0x1d0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC);
5053 rtl_eri_write(tp, 0xcc, ERIAR_MASK_1111, 0x00000050, ERIAR_EXGMAC);
5054 rtl_eri_write(tp, 0xd0, ERIAR_MASK_1111, 0x00000060, ERIAR_EXGMAC);
Hayes Wangc2218922011-09-06 16:55:18 +08005055
5056 RTL_W8(MaxTxPacketSize, EarlySize);
5057
Francois Romieu4521e1a92012-11-01 16:46:28 +00005058 rtl_disable_clock_request(pdev);
5059
Hayes Wangc2218922011-09-06 16:55:18 +08005060 RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
5061 RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
Hayes Wangc2218922011-09-06 16:55:18 +08005062 RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
Francois Romieu4521e1a92012-11-01 16:46:28 +00005063 RTL_W32(MISC, RTL_R32(MISC) | PWM_EN);
5064 RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en);
Hayes Wangc2218922011-09-06 16:55:18 +08005065}
5066
Hayes Wang5f886e02012-03-30 14:33:03 +08005067static void rtl_hw_start_8168f_1(struct rtl8169_private *tp)
5068{
5069 void __iomem *ioaddr = tp->mmio_addr;
5070 static const struct ephy_info e_info_8168f_1[] = {
5071 { 0x06, 0x00c0, 0x0020 },
5072 { 0x08, 0x0001, 0x0002 },
5073 { 0x09, 0x0000, 0x0080 },
5074 { 0x19, 0x0000, 0x0224 }
5075 };
5076
5077 rtl_hw_start_8168f(tp);
5078
Francois Romieufdf6fc02012-07-06 22:40:38 +02005079 rtl_ephy_init(tp, e_info_8168f_1, ARRAY_SIZE(e_info_8168f_1));
Hayes Wang5f886e02012-03-30 14:33:03 +08005080
Francois Romieufdf6fc02012-07-06 22:40:38 +02005081 rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0xff00, ERIAR_EXGMAC);
Hayes Wang5f886e02012-03-30 14:33:03 +08005082
5083 /* Adjust EEE LED frequency */
5084 RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07);
5085}
5086
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005087static void rtl_hw_start_8411(struct rtl8169_private *tp)
5088{
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005089 static const struct ephy_info e_info_8168f_1[] = {
5090 { 0x06, 0x00c0, 0x0020 },
5091 { 0x0f, 0xffff, 0x5200 },
5092 { 0x1e, 0x0000, 0x4000 },
5093 { 0x19, 0x0000, 0x0224 }
5094 };
5095
5096 rtl_hw_start_8168f(tp);
5097
Francois Romieufdf6fc02012-07-06 22:40:38 +02005098 rtl_ephy_init(tp, e_info_8168f_1, ARRAY_SIZE(e_info_8168f_1));
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005099
Francois Romieufdf6fc02012-07-06 22:40:38 +02005100 rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0x0000, ERIAR_EXGMAC);
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005101}
5102
Hayes Wangc5583862012-07-02 17:23:22 +08005103static void rtl_hw_start_8168g_1(struct rtl8169_private *tp)
5104{
5105 void __iomem *ioaddr = tp->mmio_addr;
5106 struct pci_dev *pdev = tp->pci_dev;
5107
5108 rtl_eri_write(tp, 0xc8, ERIAR_MASK_0101, 0x080002, ERIAR_EXGMAC);
5109 rtl_eri_write(tp, 0xcc, ERIAR_MASK_0001, 0x38, ERIAR_EXGMAC);
5110 rtl_eri_write(tp, 0xd0, ERIAR_MASK_0001, 0x48, ERIAR_EXGMAC);
5111 rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC);
5112
5113 rtl_csi_access_enable_1(tp);
5114
5115 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5116
5117 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC);
5118 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC);
5119
5120 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
Francois Romieu4521e1a92012-11-01 16:46:28 +00005121 RTL_W32(MISC, RTL_R32(MISC) & ~RXDV_GATED_EN);
Hayes Wangc5583862012-07-02 17:23:22 +08005122 RTL_W8(MaxTxPacketSize, EarlySize);
5123
5124 rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5125 rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5126
5127 /* Adjust EEE LED frequency */
5128 RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07);
5129
5130 rtl_w1w0_eri(tp, 0x2fc, ERIAR_MASK_0001, 0x01, 0x02, ERIAR_EXGMAC);
5131}
5132
Francois Romieu07ce4062007-02-23 23:36:39 +01005133static void rtl_hw_start_8168(struct net_device *dev)
5134{
Francois Romieu2dd99532007-06-11 23:22:52 +02005135 struct rtl8169_private *tp = netdev_priv(dev);
5136 void __iomem *ioaddr = tp->mmio_addr;
5137
5138 RTL_W8(Cfg9346, Cfg9346_Unlock);
5139
françois romieuf0298f82011-01-03 15:07:42 +00005140 RTL_W8(MaxTxPacketSize, TxPacketMax);
Francois Romieu2dd99532007-06-11 23:22:52 +02005141
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005142 rtl_set_rx_max_size(ioaddr, rx_buf_sz);
Francois Romieu2dd99532007-06-11 23:22:52 +02005143
Francois Romieu0e485152007-02-20 00:00:26 +01005144 tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1;
Francois Romieu2dd99532007-06-11 23:22:52 +02005145
5146 RTL_W16(CPlusCmd, tp->cp_cmd);
5147
Francois Romieu0e485152007-02-20 00:00:26 +01005148 RTL_W16(IntrMitigate, 0x5151);
5149
5150 /* Work around for RxFIFO overflow. */
françois romieu811fd302011-12-04 20:30:45 +00005151 if (tp->mac_version == RTL_GIGA_MAC_VER_11) {
Francois Romieuda78dbf2012-01-26 14:18:23 +01005152 tp->event_slow |= RxFIFOOver | PCSTimeout;
5153 tp->event_slow &= ~RxOverflow;
Francois Romieu0e485152007-02-20 00:00:26 +01005154 }
Francois Romieu2dd99532007-06-11 23:22:52 +02005155
5156 rtl_set_rx_tx_desc_registers(tp, ioaddr);
5157
Francois Romieub8363902008-06-01 12:31:57 +02005158 rtl_set_rx_mode(dev);
5159
5160 RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) |
5161 (InterFrameGap << TxInterFrameGapShift));
Francois Romieu2dd99532007-06-11 23:22:52 +02005162
5163 RTL_R8(IntrMask);
5164
Francois Romieu219a1e92008-06-28 11:58:39 +02005165 switch (tp->mac_version) {
5166 case RTL_GIGA_MAC_VER_11:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005167 rtl_hw_start_8168bb(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005168 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005169
5170 case RTL_GIGA_MAC_VER_12:
5171 case RTL_GIGA_MAC_VER_17:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005172 rtl_hw_start_8168bef(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005173 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005174
5175 case RTL_GIGA_MAC_VER_18:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005176 rtl_hw_start_8168cp_1(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005177 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005178
5179 case RTL_GIGA_MAC_VER_19:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005180 rtl_hw_start_8168c_1(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005181 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005182
5183 case RTL_GIGA_MAC_VER_20:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005184 rtl_hw_start_8168c_2(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005185 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005186
Francois Romieu197ff762008-06-28 13:16:02 +02005187 case RTL_GIGA_MAC_VER_21:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005188 rtl_hw_start_8168c_3(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005189 break;
Francois Romieu197ff762008-06-28 13:16:02 +02005190
Francois Romieu6fb07052008-06-29 11:54:28 +02005191 case RTL_GIGA_MAC_VER_22:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005192 rtl_hw_start_8168c_4(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005193 break;
Francois Romieu6fb07052008-06-29 11:54:28 +02005194
Francois Romieuef3386f2008-06-29 12:24:30 +02005195 case RTL_GIGA_MAC_VER_23:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005196 rtl_hw_start_8168cp_2(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005197 break;
Francois Romieuef3386f2008-06-29 12:24:30 +02005198
Francois Romieu7f3e3d32008-07-20 18:53:20 +02005199 case RTL_GIGA_MAC_VER_24:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005200 rtl_hw_start_8168cp_3(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005201 break;
Francois Romieu7f3e3d32008-07-20 18:53:20 +02005202
Francois Romieu5b538df2008-07-20 16:22:45 +02005203 case RTL_GIGA_MAC_VER_25:
françois romieudaf9df62009-10-07 12:44:20 +00005204 case RTL_GIGA_MAC_VER_26:
5205 case RTL_GIGA_MAC_VER_27:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005206 rtl_hw_start_8168d(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005207 break;
Francois Romieu5b538df2008-07-20 16:22:45 +02005208
françois romieue6de30d2011-01-03 15:08:37 +00005209 case RTL_GIGA_MAC_VER_28:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005210 rtl_hw_start_8168d_4(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005211 break;
Francois Romieucecb5fd2011-04-01 10:21:07 +02005212
hayeswang4804b3b2011-03-21 01:50:29 +00005213 case RTL_GIGA_MAC_VER_31:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005214 rtl_hw_start_8168dp(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005215 break;
5216
hayeswang01dc7fe2011-03-21 01:50:28 +00005217 case RTL_GIGA_MAC_VER_32:
5218 case RTL_GIGA_MAC_VER_33:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005219 rtl_hw_start_8168e_1(tp);
Hayes Wang70090422011-07-06 15:58:06 +08005220 break;
5221 case RTL_GIGA_MAC_VER_34:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005222 rtl_hw_start_8168e_2(tp);
hayeswang01dc7fe2011-03-21 01:50:28 +00005223 break;
françois romieue6de30d2011-01-03 15:08:37 +00005224
Hayes Wangc2218922011-09-06 16:55:18 +08005225 case RTL_GIGA_MAC_VER_35:
5226 case RTL_GIGA_MAC_VER_36:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005227 rtl_hw_start_8168f_1(tp);
Hayes Wangc2218922011-09-06 16:55:18 +08005228 break;
5229
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005230 case RTL_GIGA_MAC_VER_38:
5231 rtl_hw_start_8411(tp);
5232 break;
5233
Hayes Wangc5583862012-07-02 17:23:22 +08005234 case RTL_GIGA_MAC_VER_40:
5235 case RTL_GIGA_MAC_VER_41:
5236 rtl_hw_start_8168g_1(tp);
5237 break;
5238
Francois Romieu219a1e92008-06-28 11:58:39 +02005239 default:
5240 printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n",
5241 dev->name, tp->mac_version);
hayeswang4804b3b2011-03-21 01:50:29 +00005242 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005243 }
Francois Romieu2dd99532007-06-11 23:22:52 +02005244
Francois Romieu0e485152007-02-20 00:00:26 +01005245 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
5246
Francois Romieub8363902008-06-01 12:31:57 +02005247 RTL_W8(Cfg9346, Cfg9346_Lock);
5248
Francois Romieu2dd99532007-06-11 23:22:52 +02005249 RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000);
Francois Romieu07ce4062007-02-23 23:36:39 +01005250}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005251
Francois Romieu2857ffb2008-08-02 21:08:49 +02005252#define R810X_CPCMD_QUIRK_MASK (\
5253 EnableBist | \
5254 Mac_dbgo_oe | \
5255 Force_half_dup | \
françois romieu5edcc532009-08-10 19:41:52 +00005256 Force_rxflow_en | \
Francois Romieu2857ffb2008-08-02 21:08:49 +02005257 Force_txflow_en | \
5258 Cxpl_dbg_sel | \
5259 ASF | \
5260 PktCntrDisable | \
Hayes Wangd24e9aa2011-02-22 17:26:19 +08005261 Mac_dbgo_sel)
Francois Romieu2857ffb2008-08-02 21:08:49 +02005262
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005263static void rtl_hw_start_8102e_1(struct rtl8169_private *tp)
Francois Romieu2857ffb2008-08-02 21:08:49 +02005264{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005265 void __iomem *ioaddr = tp->mmio_addr;
5266 struct pci_dev *pdev = tp->pci_dev;
Alexey Dobriyan350f7592009-11-25 15:54:21 -08005267 static const struct ephy_info e_info_8102e_1[] = {
Francois Romieu2857ffb2008-08-02 21:08:49 +02005268 { 0x01, 0, 0x6e65 },
5269 { 0x02, 0, 0x091f },
5270 { 0x03, 0, 0xc2f9 },
5271 { 0x06, 0, 0xafb5 },
5272 { 0x07, 0, 0x0e00 },
5273 { 0x19, 0, 0xec80 },
5274 { 0x01, 0, 0x2e65 },
5275 { 0x01, 0, 0x6e65 }
5276 };
5277 u8 cfg1;
5278
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005279 rtl_csi_access_enable_2(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005280
5281 RTL_W8(DBG_REG, FIX_NAK_1);
5282
5283 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5284
5285 RTL_W8(Config1,
5286 LEDS1 | LEDS0 | Speed_down | MEMMAP | IOMAP | VPD | PMEnable);
5287 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
5288
5289 cfg1 = RTL_R8(Config1);
5290 if ((cfg1 & LEDS0) && (cfg1 & LEDS1))
5291 RTL_W8(Config1, cfg1 & ~LEDS0);
5292
Francois Romieufdf6fc02012-07-06 22:40:38 +02005293 rtl_ephy_init(tp, e_info_8102e_1, ARRAY_SIZE(e_info_8102e_1));
Francois Romieu2857ffb2008-08-02 21:08:49 +02005294}
5295
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005296static void rtl_hw_start_8102e_2(struct rtl8169_private *tp)
Francois Romieu2857ffb2008-08-02 21:08:49 +02005297{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005298 void __iomem *ioaddr = tp->mmio_addr;
5299 struct pci_dev *pdev = tp->pci_dev;
5300
5301 rtl_csi_access_enable_2(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005302
5303 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5304
5305 RTL_W8(Config1, MEMMAP | IOMAP | VPD | PMEnable);
5306 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005307}
5308
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005309static void rtl_hw_start_8102e_3(struct rtl8169_private *tp)
Francois Romieu2857ffb2008-08-02 21:08:49 +02005310{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005311 rtl_hw_start_8102e_2(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005312
Francois Romieufdf6fc02012-07-06 22:40:38 +02005313 rtl_ephy_write(tp, 0x03, 0xc2f9);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005314}
5315
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005316static void rtl_hw_start_8105e_1(struct rtl8169_private *tp)
Hayes Wang5a5e4442011-02-22 17:26:21 +08005317{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005318 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang5a5e4442011-02-22 17:26:21 +08005319 static const struct ephy_info e_info_8105e_1[] = {
5320 { 0x07, 0, 0x4000 },
5321 { 0x19, 0, 0x0200 },
5322 { 0x19, 0, 0x0020 },
5323 { 0x1e, 0, 0x2000 },
5324 { 0x03, 0, 0x0001 },
5325 { 0x19, 0, 0x0100 },
5326 { 0x19, 0, 0x0004 },
5327 { 0x0a, 0, 0x0020 }
5328 };
5329
Francois Romieucecb5fd2011-04-01 10:21:07 +02005330 /* Force LAN exit from ASPM if Rx/Tx are not idle */
Hayes Wang5a5e4442011-02-22 17:26:21 +08005331 RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800);
5332
Francois Romieucecb5fd2011-04-01 10:21:07 +02005333 /* Disable Early Tally Counter */
Hayes Wang5a5e4442011-02-22 17:26:21 +08005334 RTL_W32(FuncEvent, RTL_R32(FuncEvent) & ~0x010000);
5335
5336 RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET);
Hayes Wang4f6b00e52011-07-06 15:58:02 +08005337 RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
Hayes Wang5a5e4442011-02-22 17:26:21 +08005338
Francois Romieufdf6fc02012-07-06 22:40:38 +02005339 rtl_ephy_init(tp, e_info_8105e_1, ARRAY_SIZE(e_info_8105e_1));
Hayes Wang5a5e4442011-02-22 17:26:21 +08005340}
5341
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005342static void rtl_hw_start_8105e_2(struct rtl8169_private *tp)
Hayes Wang5a5e4442011-02-22 17:26:21 +08005343{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005344 rtl_hw_start_8105e_1(tp);
Francois Romieufdf6fc02012-07-06 22:40:38 +02005345 rtl_ephy_write(tp, 0x1e, rtl_ephy_read(tp, 0x1e) | 0x8000);
Hayes Wang5a5e4442011-02-22 17:26:21 +08005346}
5347
Hayes Wang7e18dca2012-03-30 14:33:02 +08005348static void rtl_hw_start_8402(struct rtl8169_private *tp)
5349{
5350 void __iomem *ioaddr = tp->mmio_addr;
5351 static const struct ephy_info e_info_8402[] = {
5352 { 0x19, 0xffff, 0xff64 },
5353 { 0x1e, 0, 0x4000 }
5354 };
5355
5356 rtl_csi_access_enable_2(tp);
5357
5358 /* Force LAN exit from ASPM if Rx/Tx are not idle */
5359 RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800);
5360
5361 RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
5362 RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
5363
Francois Romieufdf6fc02012-07-06 22:40:38 +02005364 rtl_ephy_init(tp, e_info_8402, ARRAY_SIZE(e_info_8402));
Hayes Wang7e18dca2012-03-30 14:33:02 +08005365
5366 rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT);
5367
Francois Romieufdf6fc02012-07-06 22:40:38 +02005368 rtl_eri_write(tp, 0xc8, ERIAR_MASK_1111, 0x00000002, ERIAR_EXGMAC);
5369 rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00000006, ERIAR_EXGMAC);
5370 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC);
5371 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC);
5372 rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5373 rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5374 rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0e00, 0xff00, ERIAR_EXGMAC);
Hayes Wang7e18dca2012-03-30 14:33:02 +08005375}
5376
Hayes Wang5598bfe2012-07-02 17:23:21 +08005377static void rtl_hw_start_8106(struct rtl8169_private *tp)
5378{
5379 void __iomem *ioaddr = tp->mmio_addr;
5380
5381 /* Force LAN exit from ASPM if Rx/Tx are not idle */
5382 RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800);
5383
Francois Romieu4521e1a92012-11-01 16:46:28 +00005384 RTL_W32(MISC, (RTL_R32(MISC) | DISABLE_LAN_EN) & ~EARLY_TALLY_EN);
Hayes Wang5598bfe2012-07-02 17:23:21 +08005385 RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET);
5386 RTL_W8(DLLPR, RTL_R8(DLLPR) & ~PFM_EN);
5387}
5388
Francois Romieu07ce4062007-02-23 23:36:39 +01005389static void rtl_hw_start_8101(struct net_device *dev)
5390{
Francois Romieucdf1a602007-06-11 23:29:50 +02005391 struct rtl8169_private *tp = netdev_priv(dev);
5392 void __iomem *ioaddr = tp->mmio_addr;
5393 struct pci_dev *pdev = tp->pci_dev;
5394
Francois Romieuda78dbf2012-01-26 14:18:23 +01005395 if (tp->mac_version >= RTL_GIGA_MAC_VER_30)
5396 tp->event_slow &= ~RxFIFOOver;
françois romieu811fd302011-12-04 20:30:45 +00005397
Francois Romieucecb5fd2011-04-01 10:21:07 +02005398 if (tp->mac_version == RTL_GIGA_MAC_VER_13 ||
Jiang Liu7d7903b2012-07-24 17:20:16 +08005399 tp->mac_version == RTL_GIGA_MAC_VER_16)
Bjorn Helgaas8200bc72012-08-22 10:29:42 -06005400 pcie_capability_set_word(pdev, PCI_EXP_DEVCTL,
5401 PCI_EXP_DEVCTL_NOSNOOP_EN);
Francois Romieucdf1a602007-06-11 23:29:50 +02005402
Hayes Wangd24e9aa2011-02-22 17:26:19 +08005403 RTL_W8(Cfg9346, Cfg9346_Unlock);
5404
Francois Romieu2857ffb2008-08-02 21:08:49 +02005405 switch (tp->mac_version) {
5406 case RTL_GIGA_MAC_VER_07:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005407 rtl_hw_start_8102e_1(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005408 break;
5409
5410 case RTL_GIGA_MAC_VER_08:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005411 rtl_hw_start_8102e_3(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005412 break;
5413
5414 case RTL_GIGA_MAC_VER_09:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005415 rtl_hw_start_8102e_2(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005416 break;
Hayes Wang5a5e4442011-02-22 17:26:21 +08005417
5418 case RTL_GIGA_MAC_VER_29:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005419 rtl_hw_start_8105e_1(tp);
Hayes Wang5a5e4442011-02-22 17:26:21 +08005420 break;
5421 case RTL_GIGA_MAC_VER_30:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005422 rtl_hw_start_8105e_2(tp);
Hayes Wang5a5e4442011-02-22 17:26:21 +08005423 break;
Hayes Wang7e18dca2012-03-30 14:33:02 +08005424
5425 case RTL_GIGA_MAC_VER_37:
5426 rtl_hw_start_8402(tp);
5427 break;
Hayes Wang5598bfe2012-07-02 17:23:21 +08005428
5429 case RTL_GIGA_MAC_VER_39:
5430 rtl_hw_start_8106(tp);
5431 break;
Francois Romieucdf1a602007-06-11 23:29:50 +02005432 }
5433
Hayes Wangd24e9aa2011-02-22 17:26:19 +08005434 RTL_W8(Cfg9346, Cfg9346_Lock);
Francois Romieucdf1a602007-06-11 23:29:50 +02005435
françois romieuf0298f82011-01-03 15:07:42 +00005436 RTL_W8(MaxTxPacketSize, TxPacketMax);
Francois Romieucdf1a602007-06-11 23:29:50 +02005437
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005438 rtl_set_rx_max_size(ioaddr, rx_buf_sz);
Francois Romieucdf1a602007-06-11 23:29:50 +02005439
Hayes Wangd24e9aa2011-02-22 17:26:19 +08005440 tp->cp_cmd &= ~R810X_CPCMD_QUIRK_MASK;
Francois Romieucdf1a602007-06-11 23:29:50 +02005441 RTL_W16(CPlusCmd, tp->cp_cmd);
5442
5443 RTL_W16(IntrMitigate, 0x0000);
5444
5445 rtl_set_rx_tx_desc_registers(tp, ioaddr);
5446
5447 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
5448 rtl_set_rx_tx_config_registers(tp);
5449
Francois Romieucdf1a602007-06-11 23:29:50 +02005450 RTL_R8(IntrMask);
5451
Francois Romieucdf1a602007-06-11 23:29:50 +02005452 rtl_set_rx_mode(dev);
5453
5454 RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005455}
5456
5457static int rtl8169_change_mtu(struct net_device *dev, int new_mtu)
5458{
Francois Romieud58d46b2011-05-03 16:38:29 +02005459 struct rtl8169_private *tp = netdev_priv(dev);
5460
5461 if (new_mtu < ETH_ZLEN ||
5462 new_mtu > rtl_chip_infos[tp->mac_version].jumbo_max)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005463 return -EINVAL;
5464
Francois Romieud58d46b2011-05-03 16:38:29 +02005465 if (new_mtu > ETH_DATA_LEN)
5466 rtl_hw_jumbo_enable(tp);
5467 else
5468 rtl_hw_jumbo_disable(tp);
5469
Linus Torvalds1da177e2005-04-16 15:20:36 -07005470 dev->mtu = new_mtu;
Michał Mirosław350fb322011-04-08 06:35:56 +00005471 netdev_update_features(dev);
5472
Stanislaw Gruszka323bb682010-10-20 22:25:41 +00005473 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005474}
5475
5476static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc)
5477{
Al Viro95e09182007-12-22 18:55:39 +00005478 desc->addr = cpu_to_le64(0x0badbadbadbadbadull);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005479 desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask);
5480}
5481
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005482static void rtl8169_free_rx_databuff(struct rtl8169_private *tp,
5483 void **data_buff, struct RxDesc *desc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005484{
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005485 dma_unmap_single(&tp->pci_dev->dev, le64_to_cpu(desc->addr), rx_buf_sz,
Stanislaw Gruszka231aee62010-10-20 22:25:38 +00005486 DMA_FROM_DEVICE);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005487
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005488 kfree(*data_buff);
5489 *data_buff = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005490 rtl8169_make_unusable_by_asic(desc);
5491}
5492
5493static inline void rtl8169_mark_to_asic(struct RxDesc *desc, u32 rx_buf_sz)
5494{
5495 u32 eor = le32_to_cpu(desc->opts1) & RingEnd;
5496
5497 desc->opts1 = cpu_to_le32(DescOwn | eor | rx_buf_sz);
5498}
5499
5500static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping,
5501 u32 rx_buf_sz)
5502{
5503 desc->addr = cpu_to_le64(mapping);
5504 wmb();
5505 rtl8169_mark_to_asic(desc, rx_buf_sz);
5506}
5507
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005508static inline void *rtl8169_align(void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005509{
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005510 return (void *)ALIGN((long)data, 16);
5511}
5512
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005513static struct sk_buff *rtl8169_alloc_rx_data(struct rtl8169_private *tp,
5514 struct RxDesc *desc)
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005515{
5516 void *data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005517 dma_addr_t mapping;
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005518 struct device *d = &tp->pci_dev->dev;
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005519 struct net_device *dev = tp->dev;
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005520 int node = dev->dev.parent ? dev_to_node(dev->dev.parent) : -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005521
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005522 data = kmalloc_node(rx_buf_sz, GFP_KERNEL, node);
5523 if (!data)
5524 return NULL;
Francois Romieue9f63f32007-02-28 23:16:57 +01005525
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005526 if (rtl8169_align(data) != data) {
5527 kfree(data);
5528 data = kmalloc_node(rx_buf_sz + 15, GFP_KERNEL, node);
5529 if (!data)
5530 return NULL;
5531 }
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005532
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005533 mapping = dma_map_single(d, rtl8169_align(data), rx_buf_sz,
Stanislaw Gruszka231aee62010-10-20 22:25:38 +00005534 DMA_FROM_DEVICE);
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005535 if (unlikely(dma_mapping_error(d, mapping))) {
5536 if (net_ratelimit())
5537 netif_err(tp, drv, tp->dev, "Failed to map RX DMA!\n");
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005538 goto err_out;
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005539 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005540
5541 rtl8169_map_to_asic(desc, mapping, rx_buf_sz);
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005542 return data;
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005543
5544err_out:
5545 kfree(data);
5546 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005547}
5548
5549static void rtl8169_rx_clear(struct rtl8169_private *tp)
5550{
Francois Romieu07d3f512007-02-21 22:40:46 +01005551 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005552
5553 for (i = 0; i < NUM_RX_DESC; i++) {
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005554 if (tp->Rx_databuff[i]) {
5555 rtl8169_free_rx_databuff(tp, tp->Rx_databuff + i,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005556 tp->RxDescArray + i);
5557 }
5558 }
5559}
5560
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005561static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005562{
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005563 desc->opts1 |= cpu_to_le32(RingEnd);
5564}
Francois Romieu5b0384f2006-08-16 16:00:01 +02005565
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005566static int rtl8169_rx_fill(struct rtl8169_private *tp)
5567{
5568 unsigned int i;
5569
5570 for (i = 0; i < NUM_RX_DESC; i++) {
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005571 void *data;
Francois Romieu4ae47c22007-06-16 23:28:45 +02005572
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005573 if (tp->Rx_databuff[i])
Linus Torvalds1da177e2005-04-16 15:20:36 -07005574 continue;
Francois Romieubcf0bf92006-07-26 23:14:13 +02005575
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005576 data = rtl8169_alloc_rx_data(tp, tp->RxDescArray + i);
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005577 if (!data) {
5578 rtl8169_make_unusable_by_asic(tp->RxDescArray + i);
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005579 goto err_out;
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005580 }
5581 tp->Rx_databuff[i] = data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005582 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005583
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005584 rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1);
5585 return 0;
5586
5587err_out:
5588 rtl8169_rx_clear(tp);
5589 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005590}
5591
Linus Torvalds1da177e2005-04-16 15:20:36 -07005592static int rtl8169_init_ring(struct net_device *dev)
5593{
5594 struct rtl8169_private *tp = netdev_priv(dev);
5595
5596 rtl8169_init_ring_indexes(tp);
5597
5598 memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info));
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005599 memset(tp->Rx_databuff, 0x0, NUM_RX_DESC * sizeof(void *));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005600
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005601 return rtl8169_rx_fill(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005602}
5603
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005604static void rtl8169_unmap_tx_skb(struct device *d, struct ring_info *tx_skb,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005605 struct TxDesc *desc)
5606{
5607 unsigned int len = tx_skb->len;
5608
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005609 dma_unmap_single(d, le64_to_cpu(desc->addr), len, DMA_TO_DEVICE);
5610
Linus Torvalds1da177e2005-04-16 15:20:36 -07005611 desc->opts1 = 0x00;
5612 desc->opts2 = 0x00;
5613 desc->addr = 0x00;
5614 tx_skb->len = 0;
5615}
5616
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005617static void rtl8169_tx_clear_range(struct rtl8169_private *tp, u32 start,
5618 unsigned int n)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005619{
5620 unsigned int i;
5621
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005622 for (i = 0; i < n; i++) {
5623 unsigned int entry = (start + i) % NUM_TX_DESC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005624 struct ring_info *tx_skb = tp->tx_skb + entry;
5625 unsigned int len = tx_skb->len;
5626
5627 if (len) {
5628 struct sk_buff *skb = tx_skb->skb;
5629
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005630 rtl8169_unmap_tx_skb(&tp->pci_dev->dev, tx_skb,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005631 tp->TxDescArray + entry);
5632 if (skb) {
Stanislaw Gruszkacac4b222010-10-20 22:25:40 +00005633 tp->dev->stats.tx_dropped++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005634 dev_kfree_skb(skb);
5635 tx_skb->skb = NULL;
5636 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005637 }
5638 }
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005639}
5640
5641static void rtl8169_tx_clear(struct rtl8169_private *tp)
5642{
5643 rtl8169_tx_clear_range(tp, tp->dirty_tx, NUM_TX_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005644 tp->cur_tx = tp->dirty_tx = 0;
5645}
5646
Francois Romieu4422bcd2012-01-26 11:23:32 +01005647static void rtl_reset_work(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005648{
David Howellsc4028952006-11-22 14:57:56 +00005649 struct net_device *dev = tp->dev;
Francois Romieu56de4142011-03-15 17:29:31 +01005650 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005651
Francois Romieuda78dbf2012-01-26 14:18:23 +01005652 napi_disable(&tp->napi);
5653 netif_stop_queue(dev);
5654 synchronize_sched();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005655
françois romieuc7c2c392011-12-04 20:30:52 +00005656 rtl8169_hw_reset(tp);
5657
Francois Romieu56de4142011-03-15 17:29:31 +01005658 for (i = 0; i < NUM_RX_DESC; i++)
5659 rtl8169_mark_to_asic(tp->RxDescArray + i, rx_buf_sz);
5660
Linus Torvalds1da177e2005-04-16 15:20:36 -07005661 rtl8169_tx_clear(tp);
françois romieuc7c2c392011-12-04 20:30:52 +00005662 rtl8169_init_ring_indexes(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005663
Francois Romieuda78dbf2012-01-26 14:18:23 +01005664 napi_enable(&tp->napi);
Francois Romieu56de4142011-03-15 17:29:31 +01005665 rtl_hw_start(dev);
5666 netif_wake_queue(dev);
5667 rtl8169_check_link_status(dev, tp, tp->mmio_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005668}
5669
5670static void rtl8169_tx_timeout(struct net_device *dev)
5671{
Francois Romieuda78dbf2012-01-26 14:18:23 +01005672 struct rtl8169_private *tp = netdev_priv(dev);
5673
5674 rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005675}
5676
5677static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb,
Francois Romieu2b7b4312011-04-18 22:53:24 -07005678 u32 *opts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005679{
5680 struct skb_shared_info *info = skb_shinfo(skb);
5681 unsigned int cur_frag, entry;
Jeff Garzika6343af2007-07-17 05:39:58 -04005682 struct TxDesc * uninitialized_var(txd);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005683 struct device *d = &tp->pci_dev->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005684
5685 entry = tp->cur_tx;
5686 for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) {
Eric Dumazet9e903e02011-10-18 21:00:24 +00005687 const skb_frag_t *frag = info->frags + cur_frag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005688 dma_addr_t mapping;
5689 u32 status, len;
5690 void *addr;
5691
5692 entry = (entry + 1) % NUM_TX_DESC;
5693
5694 txd = tp->TxDescArray + entry;
Eric Dumazet9e903e02011-10-18 21:00:24 +00005695 len = skb_frag_size(frag);
Ian Campbell929f6182011-08-31 00:47:06 +00005696 addr = skb_frag_address(frag);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005697 mapping = dma_map_single(d, addr, len, DMA_TO_DEVICE);
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005698 if (unlikely(dma_mapping_error(d, mapping))) {
5699 if (net_ratelimit())
5700 netif_err(tp, drv, tp->dev,
5701 "Failed to map TX fragments DMA!\n");
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005702 goto err_out;
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005703 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005704
Francois Romieucecb5fd2011-04-01 10:21:07 +02005705 /* Anti gcc 2.95.3 bugware (sic) */
Francois Romieu2b7b4312011-04-18 22:53:24 -07005706 status = opts[0] | len |
5707 (RingEnd * !((entry + 1) % NUM_TX_DESC));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005708
5709 txd->opts1 = cpu_to_le32(status);
Francois Romieu2b7b4312011-04-18 22:53:24 -07005710 txd->opts2 = cpu_to_le32(opts[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005711 txd->addr = cpu_to_le64(mapping);
5712
5713 tp->tx_skb[entry].len = len;
5714 }
5715
5716 if (cur_frag) {
5717 tp->tx_skb[entry].skb = skb;
5718 txd->opts1 |= cpu_to_le32(LastFrag);
5719 }
5720
5721 return cur_frag;
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005722
5723err_out:
5724 rtl8169_tx_clear_range(tp, tp->cur_tx + 1, cur_frag);
5725 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005726}
5727
Francois Romieu2b7b4312011-04-18 22:53:24 -07005728static inline void rtl8169_tso_csum(struct rtl8169_private *tp,
5729 struct sk_buff *skb, u32 *opts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005730{
Francois Romieu2b7b4312011-04-18 22:53:24 -07005731 const struct rtl_tx_desc_info *info = tx_desc_info + tp->txd_version;
Michał Mirosław350fb322011-04-08 06:35:56 +00005732 u32 mss = skb_shinfo(skb)->gso_size;
Francois Romieu2b7b4312011-04-18 22:53:24 -07005733 int offset = info->opts_offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005734
Francois Romieu2b7b4312011-04-18 22:53:24 -07005735 if (mss) {
5736 opts[0] |= TD_LSO;
5737 opts[offset] |= min(mss, TD_MSS_MAX) << info->mss_shift;
5738 } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -07005739 const struct iphdr *ip = ip_hdr(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005740
5741 if (ip->protocol == IPPROTO_TCP)
Francois Romieu2b7b4312011-04-18 22:53:24 -07005742 opts[offset] |= info->checksum.tcp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005743 else if (ip->protocol == IPPROTO_UDP)
Francois Romieu2b7b4312011-04-18 22:53:24 -07005744 opts[offset] |= info->checksum.udp;
5745 else
5746 WARN_ON_ONCE(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005747 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005748}
5749
Stephen Hemminger613573252009-08-31 19:50:58 +00005750static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
5751 struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005752{
5753 struct rtl8169_private *tp = netdev_priv(dev);
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005754 unsigned int entry = tp->cur_tx % NUM_TX_DESC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005755 struct TxDesc *txd = tp->TxDescArray + entry;
5756 void __iomem *ioaddr = tp->mmio_addr;
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005757 struct device *d = &tp->pci_dev->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005758 dma_addr_t mapping;
5759 u32 status, len;
Francois Romieu2b7b4312011-04-18 22:53:24 -07005760 u32 opts[2];
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005761 int frags;
Francois Romieu5b0384f2006-08-16 16:00:01 +02005762
Julien Ducourthial477206a2012-05-09 00:00:06 +02005763 if (unlikely(!TX_FRAGS_READY_FOR(tp, skb_shinfo(skb)->nr_frags))) {
Joe Perchesbf82c182010-02-09 11:49:50 +00005764 netif_err(tp, drv, dev, "BUG! Tx Ring full when queue awake!\n");
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005765 goto err_stop_0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005766 }
5767
5768 if (unlikely(le32_to_cpu(txd->opts1) & DescOwn))
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005769 goto err_stop_0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005770
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005771 len = skb_headlen(skb);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005772 mapping = dma_map_single(d, skb->data, len, DMA_TO_DEVICE);
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005773 if (unlikely(dma_mapping_error(d, mapping))) {
5774 if (net_ratelimit())
5775 netif_err(tp, drv, dev, "Failed to map TX DMA!\n");
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005776 goto err_dma_0;
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005777 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005778
5779 tp->tx_skb[entry].len = len;
5780 txd->addr = cpu_to_le64(mapping);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005781
Kirill Smelkov810f4892012-11-10 21:11:02 +04005782 opts[1] = cpu_to_le32(rtl8169_tx_vlan_tag(skb));
Francois Romieu2b7b4312011-04-18 22:53:24 -07005783 opts[0] = DescOwn;
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005784
Francois Romieu2b7b4312011-04-18 22:53:24 -07005785 rtl8169_tso_csum(tp, skb, opts);
5786
5787 frags = rtl8169_xmit_frags(tp, skb, opts);
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005788 if (frags < 0)
5789 goto err_dma_1;
5790 else if (frags)
Francois Romieu2b7b4312011-04-18 22:53:24 -07005791 opts[0] |= FirstFrag;
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005792 else {
Francois Romieu2b7b4312011-04-18 22:53:24 -07005793 opts[0] |= FirstFrag | LastFrag;
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005794 tp->tx_skb[entry].skb = skb;
5795 }
5796
Francois Romieu2b7b4312011-04-18 22:53:24 -07005797 txd->opts2 = cpu_to_le32(opts[1]);
5798
Richard Cochran5047fb52012-03-10 07:29:42 +00005799 skb_tx_timestamp(skb);
5800
Linus Torvalds1da177e2005-04-16 15:20:36 -07005801 wmb();
5802
Francois Romieucecb5fd2011-04-01 10:21:07 +02005803 /* Anti gcc 2.95.3 bugware (sic) */
Francois Romieu2b7b4312011-04-18 22:53:24 -07005804 status = opts[0] | len | (RingEnd * !((entry + 1) % NUM_TX_DESC));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005805 txd->opts1 = cpu_to_le32(status);
5806
Linus Torvalds1da177e2005-04-16 15:20:36 -07005807 tp->cur_tx += frags + 1;
5808
David Dillow4c020a92010-03-03 16:33:10 +00005809 wmb();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005810
Francois Romieucecb5fd2011-04-01 10:21:07 +02005811 RTL_W8(TxPoll, NPQ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005812
Francois Romieuda78dbf2012-01-26 14:18:23 +01005813 mmiowb();
5814
Julien Ducourthial477206a2012-05-09 00:00:06 +02005815 if (!TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS)) {
Francois Romieuae1f23f2012-01-31 00:00:19 +01005816 /* Avoid wrongly optimistic queue wake-up: rtl_tx thread must
5817 * not miss a ring update when it notices a stopped queue.
5818 */
5819 smp_wmb();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005820 netif_stop_queue(dev);
Francois Romieuae1f23f2012-01-31 00:00:19 +01005821 /* Sync with rtl_tx:
5822 * - publish queue status and cur_tx ring index (write barrier)
5823 * - refresh dirty_tx ring index (read barrier).
5824 * May the current thread have a pessimistic view of the ring
5825 * status and forget to wake up queue, a racing rtl_tx thread
5826 * can't.
5827 */
Francois Romieu1e874e02012-01-27 15:05:38 +01005828 smp_mb();
Julien Ducourthial477206a2012-05-09 00:00:06 +02005829 if (TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005830 netif_wake_queue(dev);
5831 }
5832
Stephen Hemminger613573252009-08-31 19:50:58 +00005833 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005834
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005835err_dma_1:
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005836 rtl8169_unmap_tx_skb(d, tp->tx_skb + entry, txd);
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005837err_dma_0:
5838 dev_kfree_skb(skb);
5839 dev->stats.tx_dropped++;
5840 return NETDEV_TX_OK;
5841
5842err_stop_0:
Linus Torvalds1da177e2005-04-16 15:20:36 -07005843 netif_stop_queue(dev);
Francois Romieucebf8cc2007-10-18 12:06:54 +02005844 dev->stats.tx_dropped++;
Stephen Hemminger613573252009-08-31 19:50:58 +00005845 return NETDEV_TX_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005846}
5847
5848static void rtl8169_pcierr_interrupt(struct net_device *dev)
5849{
5850 struct rtl8169_private *tp = netdev_priv(dev);
5851 struct pci_dev *pdev = tp->pci_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005852 u16 pci_status, pci_cmd;
5853
5854 pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd);
5855 pci_read_config_word(pdev, PCI_STATUS, &pci_status);
5856
Joe Perchesbf82c182010-02-09 11:49:50 +00005857 netif_err(tp, intr, dev, "PCI error (cmd = 0x%04x, status = 0x%04x)\n",
5858 pci_cmd, pci_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005859
5860 /*
5861 * The recovery sequence below admits a very elaborated explanation:
5862 * - it seems to work;
Francois Romieud03902b2006-11-23 00:00:42 +01005863 * - I did not see what else could be done;
5864 * - it makes iop3xx happy.
Linus Torvalds1da177e2005-04-16 15:20:36 -07005865 *
5866 * Feel free to adjust to your needs.
5867 */
Francois Romieua27993f2006-12-18 00:04:19 +01005868 if (pdev->broken_parity_status)
Francois Romieud03902b2006-11-23 00:00:42 +01005869 pci_cmd &= ~PCI_COMMAND_PARITY;
5870 else
5871 pci_cmd |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY;
5872
5873 pci_write_config_word(pdev, PCI_COMMAND, pci_cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005874
5875 pci_write_config_word(pdev, PCI_STATUS,
5876 pci_status & (PCI_STATUS_DETECTED_PARITY |
5877 PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_REC_MASTER_ABORT |
5878 PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_SIG_TARGET_ABORT));
5879
5880 /* The infamous DAC f*ckup only happens at boot time */
Timo Teräs9fba0812013-01-15 21:01:24 +00005881 if ((tp->cp_cmd & PCIDAC) && !tp->cur_rx) {
françois romieue6de30d2011-01-03 15:08:37 +00005882 void __iomem *ioaddr = tp->mmio_addr;
5883
Joe Perchesbf82c182010-02-09 11:49:50 +00005884 netif_info(tp, intr, dev, "disabling PCI DAC\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005885 tp->cp_cmd &= ~PCIDAC;
5886 RTL_W16(CPlusCmd, tp->cp_cmd);
5887 dev->features &= ~NETIF_F_HIGHDMA;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005888 }
5889
françois romieue6de30d2011-01-03 15:08:37 +00005890 rtl8169_hw_reset(tp);
Francois Romieud03902b2006-11-23 00:00:42 +01005891
Francois Romieu98ddf982012-01-31 10:47:34 +01005892 rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005893}
5894
Francois Romieuda78dbf2012-01-26 14:18:23 +01005895static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005896{
5897 unsigned int dirty_tx, tx_left;
5898
Linus Torvalds1da177e2005-04-16 15:20:36 -07005899 dirty_tx = tp->dirty_tx;
5900 smp_rmb();
5901 tx_left = tp->cur_tx - dirty_tx;
5902
5903 while (tx_left > 0) {
5904 unsigned int entry = dirty_tx % NUM_TX_DESC;
5905 struct ring_info *tx_skb = tp->tx_skb + entry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005906 u32 status;
5907
5908 rmb();
5909 status = le32_to_cpu(tp->TxDescArray[entry].opts1);
5910 if (status & DescOwn)
5911 break;
5912
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005913 rtl8169_unmap_tx_skb(&tp->pci_dev->dev, tx_skb,
5914 tp->TxDescArray + entry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005915 if (status & LastFrag) {
Francois Romieu17bcb682012-07-23 22:55:55 +02005916 u64_stats_update_begin(&tp->tx_stats.syncp);
5917 tp->tx_stats.packets++;
5918 tp->tx_stats.bytes += tx_skb->skb->len;
5919 u64_stats_update_end(&tp->tx_stats.syncp);
5920 dev_kfree_skb(tx_skb->skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005921 tx_skb->skb = NULL;
5922 }
5923 dirty_tx++;
5924 tx_left--;
5925 }
5926
5927 if (tp->dirty_tx != dirty_tx) {
5928 tp->dirty_tx = dirty_tx;
Francois Romieuae1f23f2012-01-31 00:00:19 +01005929 /* Sync with rtl8169_start_xmit:
5930 * - publish dirty_tx ring index (write barrier)
5931 * - refresh cur_tx ring index and queue status (read barrier)
5932 * May the current thread miss the stopped queue condition,
5933 * a racing xmit thread can only have a right view of the
5934 * ring status.
5935 */
Francois Romieu1e874e02012-01-27 15:05:38 +01005936 smp_mb();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005937 if (netif_queue_stopped(dev) &&
Julien Ducourthial477206a2012-05-09 00:00:06 +02005938 TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005939 netif_wake_queue(dev);
5940 }
Francois Romieud78ae2d2007-08-26 20:08:19 +02005941 /*
5942 * 8168 hack: TxPoll requests are lost when the Tx packets are
5943 * too close. Let's kick an extra TxPoll request when a burst
5944 * of start_xmit activity is detected (if it is not detected,
5945 * it is slow enough). -- FR
5946 */
Francois Romieuda78dbf2012-01-26 14:18:23 +01005947 if (tp->cur_tx != dirty_tx) {
5948 void __iomem *ioaddr = tp->mmio_addr;
5949
Francois Romieud78ae2d2007-08-26 20:08:19 +02005950 RTL_W8(TxPoll, NPQ);
Francois Romieuda78dbf2012-01-26 14:18:23 +01005951 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005952 }
5953}
5954
Francois Romieu126fa4b2005-05-12 20:09:17 -04005955static inline int rtl8169_fragmented_frame(u32 status)
5956{
5957 return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag);
5958}
5959
Eric Dumazetadea1ac72010-09-05 20:04:05 -07005960static inline void rtl8169_rx_csum(struct sk_buff *skb, u32 opts1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005961{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005962 u32 status = opts1 & RxProtoMask;
5963
5964 if (((status == RxProtoTCP) && !(opts1 & TCPFail)) ||
Shan Weid5d3ebe2010-11-12 00:15:25 +00005965 ((status == RxProtoUDP) && !(opts1 & UDPFail)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005966 skb->ip_summed = CHECKSUM_UNNECESSARY;
5967 else
Eric Dumazetbc8acf22010-09-02 13:07:41 -07005968 skb_checksum_none_assert(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005969}
5970
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005971static struct sk_buff *rtl8169_try_rx_copy(void *data,
5972 struct rtl8169_private *tp,
5973 int pkt_size,
5974 dma_addr_t addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005975{
Stephen Hemmingerb4496552007-06-17 01:06:49 +02005976 struct sk_buff *skb;
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005977 struct device *d = &tp->pci_dev->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005978
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005979 data = rtl8169_align(data);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005980 dma_sync_single_for_cpu(d, addr, pkt_size, DMA_FROM_DEVICE);
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005981 prefetch(data);
5982 skb = netdev_alloc_skb_ip_align(tp->dev, pkt_size);
5983 if (skb)
5984 memcpy(skb->data, data, pkt_size);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005985 dma_sync_single_for_device(d, addr, pkt_size, DMA_FROM_DEVICE);
5986
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005987 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005988}
5989
Francois Romieuda78dbf2012-01-26 14:18:23 +01005990static int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, u32 budget)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005991{
5992 unsigned int cur_rx, rx_left;
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005993 unsigned int count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005994
Linus Torvalds1da177e2005-04-16 15:20:36 -07005995 cur_rx = tp->cur_rx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005996
Timo Teräs9fba0812013-01-15 21:01:24 +00005997 for (rx_left = min(budget, NUM_RX_DESC); rx_left > 0; rx_left--, cur_rx++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005998 unsigned int entry = cur_rx % NUM_RX_DESC;
Francois Romieu126fa4b2005-05-12 20:09:17 -04005999 struct RxDesc *desc = tp->RxDescArray + entry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006000 u32 status;
6001
6002 rmb();
David S. Miller8decf862011-09-22 03:23:13 -04006003 status = le32_to_cpu(desc->opts1) & tp->opts1_mask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006004
6005 if (status & DescOwn)
6006 break;
Richard Dawe4dcb7d32005-05-27 21:12:00 +02006007 if (unlikely(status & RxRES)) {
Joe Perchesbf82c182010-02-09 11:49:50 +00006008 netif_info(tp, rx_err, dev, "Rx ERROR. status = %08x\n",
6009 status);
Francois Romieucebf8cc2007-10-18 12:06:54 +02006010 dev->stats.rx_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006011 if (status & (RxRWT | RxRUNT))
Francois Romieucebf8cc2007-10-18 12:06:54 +02006012 dev->stats.rx_length_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006013 if (status & RxCRC)
Francois Romieucebf8cc2007-10-18 12:06:54 +02006014 dev->stats.rx_crc_errors++;
Francois Romieu9dccf612006-05-14 12:31:17 +02006015 if (status & RxFOVF) {
Francois Romieuda78dbf2012-01-26 14:18:23 +01006016 rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
Francois Romieucebf8cc2007-10-18 12:06:54 +02006017 dev->stats.rx_fifo_errors++;
Francois Romieu9dccf612006-05-14 12:31:17 +02006018 }
Ben Greear6bbe0212012-02-10 15:04:33 +00006019 if ((status & (RxRUNT | RxCRC)) &&
6020 !(status & (RxRWT | RxFOVF)) &&
6021 (dev->features & NETIF_F_RXALL))
6022 goto process_pkt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006023 } else {
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006024 struct sk_buff *skb;
Ben Greear6bbe0212012-02-10 15:04:33 +00006025 dma_addr_t addr;
6026 int pkt_size;
6027
6028process_pkt:
6029 addr = le64_to_cpu(desc->addr);
Ben Greear79d0c1d2012-02-10 15:04:34 +00006030 if (likely(!(dev->features & NETIF_F_RXFCS)))
6031 pkt_size = (status & 0x00003fff) - 4;
6032 else
6033 pkt_size = status & 0x00003fff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006034
Francois Romieu126fa4b2005-05-12 20:09:17 -04006035 /*
6036 * The driver does not support incoming fragmented
6037 * frames. They are seen as a symptom of over-mtu
6038 * sized frames.
6039 */
6040 if (unlikely(rtl8169_fragmented_frame(status))) {
Francois Romieucebf8cc2007-10-18 12:06:54 +02006041 dev->stats.rx_dropped++;
6042 dev->stats.rx_length_errors++;
françois romieuce11ff52013-01-24 13:30:06 +00006043 goto release_descriptor;
Francois Romieu126fa4b2005-05-12 20:09:17 -04006044 }
6045
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006046 skb = rtl8169_try_rx_copy(tp->Rx_databuff[entry],
6047 tp, pkt_size, addr);
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006048 if (!skb) {
6049 dev->stats.rx_dropped++;
françois romieuce11ff52013-01-24 13:30:06 +00006050 goto release_descriptor;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006051 }
6052
Eric Dumazetadea1ac72010-09-05 20:04:05 -07006053 rtl8169_rx_csum(skb, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006054 skb_put(skb, pkt_size);
6055 skb->protocol = eth_type_trans(skb, dev);
6056
Francois Romieu7a8fc772011-03-01 17:18:33 +01006057 rtl8169_rx_vlan_tag(desc, skb);
6058
Francois Romieu56de4142011-03-15 17:29:31 +01006059 napi_gro_receive(&tp->napi, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006060
Junchang Wang8027aa22012-03-04 23:30:32 +01006061 u64_stats_update_begin(&tp->rx_stats.syncp);
6062 tp->rx_stats.packets++;
6063 tp->rx_stats.bytes += pkt_size;
6064 u64_stats_update_end(&tp->rx_stats.syncp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006065 }
françois romieuce11ff52013-01-24 13:30:06 +00006066release_descriptor:
6067 desc->opts2 = 0;
6068 wmb();
6069 rtl8169_mark_to_asic(desc, rx_buf_sz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006070 }
6071
6072 count = cur_rx - tp->cur_rx;
6073 tp->cur_rx = cur_rx;
6074
Linus Torvalds1da177e2005-04-16 15:20:36 -07006075 return count;
6076}
6077
Francois Romieu07d3f512007-02-21 22:40:46 +01006078static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006079{
Francois Romieu07d3f512007-02-21 22:40:46 +01006080 struct net_device *dev = dev_instance;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006081 struct rtl8169_private *tp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006082 int handled = 0;
Francois Romieu9085cdfa2012-01-26 12:59:08 +01006083 u16 status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006084
Francois Romieu9085cdfa2012-01-26 12:59:08 +01006085 status = rtl_get_events(tp);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006086 if (status && status != 0xffff) {
6087 status &= RTL_EVENT_NAPI | tp->event_slow;
6088 if (status) {
6089 handled = 1;
françois romieu811fd302011-12-04 20:30:45 +00006090
Francois Romieuda78dbf2012-01-26 14:18:23 +01006091 rtl_irq_disable(tp);
6092 napi_schedule(&tp->napi);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006093 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006094 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006095 return IRQ_RETVAL(handled);
6096}
6097
Francois Romieuda78dbf2012-01-26 14:18:23 +01006098/*
6099 * Workqueue context.
6100 */
6101static void rtl_slow_event_work(struct rtl8169_private *tp)
6102{
6103 struct net_device *dev = tp->dev;
6104 u16 status;
6105
6106 status = rtl_get_events(tp) & tp->event_slow;
6107 rtl_ack_events(tp, status);
6108
6109 if (unlikely(status & RxFIFOOver)) {
6110 switch (tp->mac_version) {
6111 /* Work around for rx fifo overflow */
6112 case RTL_GIGA_MAC_VER_11:
6113 netif_stop_queue(dev);
Francois Romieu934714d2012-01-31 11:09:21 +01006114 /* XXX - Hack alert. See rtl_task(). */
6115 set_bit(RTL_FLAG_TASK_RESET_PENDING, tp->wk.flags);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006116 default:
6117 break;
6118 }
6119 }
6120
6121 if (unlikely(status & SYSErr))
6122 rtl8169_pcierr_interrupt(dev);
6123
6124 if (status & LinkChg)
6125 __rtl8169_check_link_status(dev, tp, tp->mmio_addr, true);
6126
françois romieu7dbb4912012-06-09 10:53:16 +00006127 rtl_irq_enable_all(tp);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006128}
6129
Francois Romieu4422bcd2012-01-26 11:23:32 +01006130static void rtl_task(struct work_struct *work)
6131{
Francois Romieuda78dbf2012-01-26 14:18:23 +01006132 static const struct {
6133 int bitnr;
6134 void (*action)(struct rtl8169_private *);
6135 } rtl_work[] = {
Francois Romieu934714d2012-01-31 11:09:21 +01006136 /* XXX - keep rtl_slow_event_work() as first element. */
Francois Romieuda78dbf2012-01-26 14:18:23 +01006137 { RTL_FLAG_TASK_SLOW_PENDING, rtl_slow_event_work },
6138 { RTL_FLAG_TASK_RESET_PENDING, rtl_reset_work },
6139 { RTL_FLAG_TASK_PHY_PENDING, rtl_phy_work }
6140 };
Francois Romieu4422bcd2012-01-26 11:23:32 +01006141 struct rtl8169_private *tp =
6142 container_of(work, struct rtl8169_private, wk.work);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006143 struct net_device *dev = tp->dev;
6144 int i;
Francois Romieu4422bcd2012-01-26 11:23:32 +01006145
Francois Romieuda78dbf2012-01-26 14:18:23 +01006146 rtl_lock_work(tp);
6147
Francois Romieu6c4a70c2012-01-31 10:56:44 +01006148 if (!netif_running(dev) ||
6149 !test_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags))
Francois Romieuda78dbf2012-01-26 14:18:23 +01006150 goto out_unlock;
6151
6152 for (i = 0; i < ARRAY_SIZE(rtl_work); i++) {
6153 bool pending;
6154
Francois Romieuda78dbf2012-01-26 14:18:23 +01006155 pending = test_and_clear_bit(rtl_work[i].bitnr, tp->wk.flags);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006156 if (pending)
6157 rtl_work[i].action(tp);
6158 }
6159
6160out_unlock:
6161 rtl_unlock_work(tp);
Francois Romieu4422bcd2012-01-26 11:23:32 +01006162}
6163
Stephen Hemmingerbea33482007-10-03 16:41:36 -07006164static int rtl8169_poll(struct napi_struct *napi, int budget)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006165{
Stephen Hemmingerbea33482007-10-03 16:41:36 -07006166 struct rtl8169_private *tp = container_of(napi, struct rtl8169_private, napi);
6167 struct net_device *dev = tp->dev;
Francois Romieuda78dbf2012-01-26 14:18:23 +01006168 u16 enable_mask = RTL_EVENT_NAPI | tp->event_slow;
6169 int work_done= 0;
6170 u16 status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006171
Francois Romieuda78dbf2012-01-26 14:18:23 +01006172 status = rtl_get_events(tp);
6173 rtl_ack_events(tp, status & ~tp->event_slow);
6174
6175 if (status & RTL_EVENT_NAPI_RX)
6176 work_done = rtl_rx(dev, tp, (u32) budget);
6177
6178 if (status & RTL_EVENT_NAPI_TX)
6179 rtl_tx(dev, tp);
6180
6181 if (status & tp->event_slow) {
6182 enable_mask &= ~tp->event_slow;
6183
6184 rtl_schedule_task(tp, RTL_FLAG_TASK_SLOW_PENDING);
6185 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006186
Stephen Hemmingerbea33482007-10-03 16:41:36 -07006187 if (work_done < budget) {
Ben Hutchings288379f2009-01-19 16:43:59 -08006188 napi_complete(napi);
David Dillowf11a3772009-05-22 15:29:34 +00006189
Francois Romieuda78dbf2012-01-26 14:18:23 +01006190 rtl_irq_enable(tp, enable_mask);
6191 mmiowb();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006192 }
6193
Stephen Hemmingerbea33482007-10-03 16:41:36 -07006194 return work_done;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006195}
Linus Torvalds1da177e2005-04-16 15:20:36 -07006196
Francois Romieu523a6092008-09-10 22:28:56 +02006197static void rtl8169_rx_missed(struct net_device *dev, void __iomem *ioaddr)
6198{
6199 struct rtl8169_private *tp = netdev_priv(dev);
6200
6201 if (tp->mac_version > RTL_GIGA_MAC_VER_06)
6202 return;
6203
6204 dev->stats.rx_missed_errors += (RTL_R32(RxMissed) & 0xffffff);
6205 RTL_W32(RxMissed, 0);
6206}
6207
Linus Torvalds1da177e2005-04-16 15:20:36 -07006208static void rtl8169_down(struct net_device *dev)
6209{
6210 struct rtl8169_private *tp = netdev_priv(dev);
6211 void __iomem *ioaddr = tp->mmio_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006212
Francois Romieu4876cc12011-03-11 21:07:11 +01006213 del_timer_sync(&tp->timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006214
Stephen Hemminger93dd79e2007-10-28 17:14:06 +01006215 napi_disable(&tp->napi);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006216 netif_stop_queue(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006217
Hayes Wang92fc43b2011-07-06 15:58:03 +08006218 rtl8169_hw_reset(tp);
Stanislaw Gruszka323bb682010-10-20 22:25:41 +00006219 /*
6220 * At this point device interrupts can not be enabled in any function,
Francois Romieu209e5ac2012-01-26 09:59:50 +01006221 * as netif_running is not true (rtl8169_interrupt, rtl8169_reset_task)
6222 * and napi is disabled (rtl8169_poll).
Stanislaw Gruszka323bb682010-10-20 22:25:41 +00006223 */
Francois Romieu523a6092008-09-10 22:28:56 +02006224 rtl8169_rx_missed(dev, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006225
Linus Torvalds1da177e2005-04-16 15:20:36 -07006226 /* Give a racing hard_start_xmit a few cycles to complete. */
Francois Romieuda78dbf2012-01-26 14:18:23 +01006227 synchronize_sched();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006228
Linus Torvalds1da177e2005-04-16 15:20:36 -07006229 rtl8169_tx_clear(tp);
6230
6231 rtl8169_rx_clear(tp);
françois romieu065c27c2011-01-03 15:08:12 +00006232
6233 rtl_pll_power_down(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006234}
6235
6236static int rtl8169_close(struct net_device *dev)
6237{
6238 struct rtl8169_private *tp = netdev_priv(dev);
6239 struct pci_dev *pdev = tp->pci_dev;
6240
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006241 pm_runtime_get_sync(&pdev->dev);
6242
Francois Romieucecb5fd2011-04-01 10:21:07 +02006243 /* Update counters before going down */
Ivan Vecera355423d2009-02-06 21:49:57 -08006244 rtl8169_update_counters(dev);
6245
Francois Romieuda78dbf2012-01-26 14:18:23 +01006246 rtl_lock_work(tp);
Francois Romieu6c4a70c2012-01-31 10:56:44 +01006247 clear_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006248
Linus Torvalds1da177e2005-04-16 15:20:36 -07006249 rtl8169_down(dev);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006250 rtl_unlock_work(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006251
Francois Romieu92a7c4e2012-03-10 10:42:12 +01006252 free_irq(pdev->irq, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006253
Stanislaw Gruszka82553bb2010-10-08 04:25:01 +00006254 dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray,
6255 tp->RxPhyAddr);
6256 dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray,
6257 tp->TxPhyAddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006258 tp->TxDescArray = NULL;
6259 tp->RxDescArray = NULL;
6260
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006261 pm_runtime_put_sync(&pdev->dev);
6262
Linus Torvalds1da177e2005-04-16 15:20:36 -07006263 return 0;
6264}
6265
Francois Romieudc1c00c2012-03-08 10:06:18 +01006266#ifdef CONFIG_NET_POLL_CONTROLLER
6267static void rtl8169_netpoll(struct net_device *dev)
6268{
6269 struct rtl8169_private *tp = netdev_priv(dev);
6270
6271 rtl8169_interrupt(tp->pci_dev->irq, dev);
6272}
6273#endif
6274
Francois Romieudf43ac72012-03-08 09:48:40 +01006275static int rtl_open(struct net_device *dev)
6276{
6277 struct rtl8169_private *tp = netdev_priv(dev);
6278 void __iomem *ioaddr = tp->mmio_addr;
6279 struct pci_dev *pdev = tp->pci_dev;
6280 int retval = -ENOMEM;
6281
6282 pm_runtime_get_sync(&pdev->dev);
6283
6284 /*
Jiri Kosinae75d6602012-04-08 21:48:52 +02006285 * Rx and Tx descriptors needs 256 bytes alignment.
Francois Romieudf43ac72012-03-08 09:48:40 +01006286 * dma_alloc_coherent provides more.
6287 */
6288 tp->TxDescArray = dma_alloc_coherent(&pdev->dev, R8169_TX_RING_BYTES,
6289 &tp->TxPhyAddr, GFP_KERNEL);
6290 if (!tp->TxDescArray)
6291 goto err_pm_runtime_put;
6292
6293 tp->RxDescArray = dma_alloc_coherent(&pdev->dev, R8169_RX_RING_BYTES,
6294 &tp->RxPhyAddr, GFP_KERNEL);
6295 if (!tp->RxDescArray)
6296 goto err_free_tx_0;
6297
6298 retval = rtl8169_init_ring(dev);
6299 if (retval < 0)
6300 goto err_free_rx_1;
6301
6302 INIT_WORK(&tp->wk.work, rtl_task);
6303
6304 smp_mb();
6305
6306 rtl_request_firmware(tp);
6307
Francois Romieu92a7c4e2012-03-10 10:42:12 +01006308 retval = request_irq(pdev->irq, rtl8169_interrupt,
Francois Romieudf43ac72012-03-08 09:48:40 +01006309 (tp->features & RTL_FEATURE_MSI) ? 0 : IRQF_SHARED,
6310 dev->name, dev);
6311 if (retval < 0)
6312 goto err_release_fw_2;
6313
6314 rtl_lock_work(tp);
6315
6316 set_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
6317
6318 napi_enable(&tp->napi);
6319
6320 rtl8169_init_phy(dev, tp);
6321
6322 __rtl8169_set_features(dev, dev->features);
6323
6324 rtl_pll_power_up(tp);
6325
6326 rtl_hw_start(dev);
6327
6328 netif_start_queue(dev);
6329
6330 rtl_unlock_work(tp);
6331
6332 tp->saved_wolopts = 0;
6333 pm_runtime_put_noidle(&pdev->dev);
6334
6335 rtl8169_check_link_status(dev, tp, ioaddr);
6336out:
6337 return retval;
6338
6339err_release_fw_2:
6340 rtl_release_firmware(tp);
6341 rtl8169_rx_clear(tp);
6342err_free_rx_1:
6343 dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray,
6344 tp->RxPhyAddr);
6345 tp->RxDescArray = NULL;
6346err_free_tx_0:
6347 dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray,
6348 tp->TxPhyAddr);
6349 tp->TxDescArray = NULL;
6350err_pm_runtime_put:
6351 pm_runtime_put_noidle(&pdev->dev);
6352 goto out;
6353}
6354
Junchang Wang8027aa22012-03-04 23:30:32 +01006355static struct rtnl_link_stats64 *
6356rtl8169_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006357{
6358 struct rtl8169_private *tp = netdev_priv(dev);
6359 void __iomem *ioaddr = tp->mmio_addr;
Junchang Wang8027aa22012-03-04 23:30:32 +01006360 unsigned int start;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006361
Francois Romieuda78dbf2012-01-26 14:18:23 +01006362 if (netif_running(dev))
Francois Romieu523a6092008-09-10 22:28:56 +02006363 rtl8169_rx_missed(dev, ioaddr);
Francois Romieu5b0384f2006-08-16 16:00:01 +02006364
Junchang Wang8027aa22012-03-04 23:30:32 +01006365 do {
6366 start = u64_stats_fetch_begin_bh(&tp->rx_stats.syncp);
6367 stats->rx_packets = tp->rx_stats.packets;
6368 stats->rx_bytes = tp->rx_stats.bytes;
6369 } while (u64_stats_fetch_retry_bh(&tp->rx_stats.syncp, start));
6370
6371
6372 do {
6373 start = u64_stats_fetch_begin_bh(&tp->tx_stats.syncp);
6374 stats->tx_packets = tp->tx_stats.packets;
6375 stats->tx_bytes = tp->tx_stats.bytes;
6376 } while (u64_stats_fetch_retry_bh(&tp->tx_stats.syncp, start));
6377
6378 stats->rx_dropped = dev->stats.rx_dropped;
6379 stats->tx_dropped = dev->stats.tx_dropped;
6380 stats->rx_length_errors = dev->stats.rx_length_errors;
6381 stats->rx_errors = dev->stats.rx_errors;
6382 stats->rx_crc_errors = dev->stats.rx_crc_errors;
6383 stats->rx_fifo_errors = dev->stats.rx_fifo_errors;
6384 stats->rx_missed_errors = dev->stats.rx_missed_errors;
6385
6386 return stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006387}
6388
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006389static void rtl8169_net_suspend(struct net_device *dev)
Francois Romieu5d06a992006-02-23 00:47:58 +01006390{
françois romieu065c27c2011-01-03 15:08:12 +00006391 struct rtl8169_private *tp = netdev_priv(dev);
6392
Francois Romieu5d06a992006-02-23 00:47:58 +01006393 if (!netif_running(dev))
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006394 return;
Francois Romieu5d06a992006-02-23 00:47:58 +01006395
6396 netif_device_detach(dev);
6397 netif_stop_queue(dev);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006398
6399 rtl_lock_work(tp);
6400 napi_disable(&tp->napi);
Francois Romieu6c4a70c2012-01-31 10:56:44 +01006401 clear_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006402 rtl_unlock_work(tp);
6403
6404 rtl_pll_power_down(tp);
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006405}
Francois Romieu5d06a992006-02-23 00:47:58 +01006406
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006407#ifdef CONFIG_PM
6408
6409static int rtl8169_suspend(struct device *device)
6410{
6411 struct pci_dev *pdev = to_pci_dev(device);
6412 struct net_device *dev = pci_get_drvdata(pdev);
6413
6414 rtl8169_net_suspend(dev);
Francois Romieu1371fa62007-04-02 23:01:11 +02006415
Francois Romieu5d06a992006-02-23 00:47:58 +01006416 return 0;
6417}
6418
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006419static void __rtl8169_resume(struct net_device *dev)
6420{
françois romieu065c27c2011-01-03 15:08:12 +00006421 struct rtl8169_private *tp = netdev_priv(dev);
6422
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006423 netif_device_attach(dev);
françois romieu065c27c2011-01-03 15:08:12 +00006424
6425 rtl_pll_power_up(tp);
6426
Artem Savkovcff4c162012-04-03 10:29:11 +00006427 rtl_lock_work(tp);
6428 napi_enable(&tp->napi);
Francois Romieu6c4a70c2012-01-31 10:56:44 +01006429 set_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
Artem Savkovcff4c162012-04-03 10:29:11 +00006430 rtl_unlock_work(tp);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006431
Francois Romieu98ddf982012-01-31 10:47:34 +01006432 rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006433}
6434
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006435static int rtl8169_resume(struct device *device)
Francois Romieu5d06a992006-02-23 00:47:58 +01006436{
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006437 struct pci_dev *pdev = to_pci_dev(device);
Francois Romieu5d06a992006-02-23 00:47:58 +01006438 struct net_device *dev = pci_get_drvdata(pdev);
Stanislaw Gruszkafccec102010-10-20 22:25:42 +00006439 struct rtl8169_private *tp = netdev_priv(dev);
6440
6441 rtl8169_init_phy(dev, tp);
Francois Romieu5d06a992006-02-23 00:47:58 +01006442
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006443 if (netif_running(dev))
6444 __rtl8169_resume(dev);
Francois Romieu5d06a992006-02-23 00:47:58 +01006445
Francois Romieu5d06a992006-02-23 00:47:58 +01006446 return 0;
6447}
6448
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006449static int rtl8169_runtime_suspend(struct device *device)
6450{
6451 struct pci_dev *pdev = to_pci_dev(device);
6452 struct net_device *dev = pci_get_drvdata(pdev);
6453 struct rtl8169_private *tp = netdev_priv(dev);
6454
6455 if (!tp->TxDescArray)
6456 return 0;
6457
Francois Romieuda78dbf2012-01-26 14:18:23 +01006458 rtl_lock_work(tp);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006459 tp->saved_wolopts = __rtl8169_get_wol(tp);
6460 __rtl8169_set_wol(tp, WAKE_ANY);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006461 rtl_unlock_work(tp);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006462
6463 rtl8169_net_suspend(dev);
6464
6465 return 0;
6466}
6467
6468static int rtl8169_runtime_resume(struct device *device)
6469{
6470 struct pci_dev *pdev = to_pci_dev(device);
6471 struct net_device *dev = pci_get_drvdata(pdev);
6472 struct rtl8169_private *tp = netdev_priv(dev);
6473
6474 if (!tp->TxDescArray)
6475 return 0;
6476
Francois Romieuda78dbf2012-01-26 14:18:23 +01006477 rtl_lock_work(tp);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006478 __rtl8169_set_wol(tp, tp->saved_wolopts);
6479 tp->saved_wolopts = 0;
Francois Romieuda78dbf2012-01-26 14:18:23 +01006480 rtl_unlock_work(tp);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006481
Stanislaw Gruszkafccec102010-10-20 22:25:42 +00006482 rtl8169_init_phy(dev, tp);
6483
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006484 __rtl8169_resume(dev);
6485
6486 return 0;
6487}
6488
6489static int rtl8169_runtime_idle(struct device *device)
6490{
6491 struct pci_dev *pdev = to_pci_dev(device);
6492 struct net_device *dev = pci_get_drvdata(pdev);
6493 struct rtl8169_private *tp = netdev_priv(dev);
6494
Rafael J. Wysockie4fbce72010-12-08 15:32:14 +00006495 return tp->TxDescArray ? -EBUSY : 0;
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006496}
6497
Alexey Dobriyan47145212009-12-14 18:00:08 -08006498static const struct dev_pm_ops rtl8169_pm_ops = {
Francois Romieucecb5fd2011-04-01 10:21:07 +02006499 .suspend = rtl8169_suspend,
6500 .resume = rtl8169_resume,
6501 .freeze = rtl8169_suspend,
6502 .thaw = rtl8169_resume,
6503 .poweroff = rtl8169_suspend,
6504 .restore = rtl8169_resume,
6505 .runtime_suspend = rtl8169_runtime_suspend,
6506 .runtime_resume = rtl8169_runtime_resume,
6507 .runtime_idle = rtl8169_runtime_idle,
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006508};
6509
6510#define RTL8169_PM_OPS (&rtl8169_pm_ops)
6511
6512#else /* !CONFIG_PM */
6513
6514#define RTL8169_PM_OPS NULL
6515
6516#endif /* !CONFIG_PM */
6517
David S. Miller1805b2f2011-10-24 18:18:09 -04006518static void rtl_wol_shutdown_quirk(struct rtl8169_private *tp)
6519{
6520 void __iomem *ioaddr = tp->mmio_addr;
6521
6522 /* WoL fails with 8168b when the receiver is disabled. */
6523 switch (tp->mac_version) {
6524 case RTL_GIGA_MAC_VER_11:
6525 case RTL_GIGA_MAC_VER_12:
6526 case RTL_GIGA_MAC_VER_17:
6527 pci_clear_master(tp->pci_dev);
6528
6529 RTL_W8(ChipCmd, CmdRxEnb);
6530 /* PCI commit */
6531 RTL_R8(ChipCmd);
6532 break;
6533 default:
6534 break;
6535 }
6536}
6537
Francois Romieu1765f952008-09-13 17:21:40 +02006538static void rtl_shutdown(struct pci_dev *pdev)
6539{
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006540 struct net_device *dev = pci_get_drvdata(pdev);
françois romieu4bb3f522009-06-17 11:41:45 +00006541 struct rtl8169_private *tp = netdev_priv(dev);
françois romieu2a15cd22012-03-06 01:14:12 +00006542 struct device *d = &pdev->dev;
6543
6544 pm_runtime_get_sync(d);
Francois Romieu1765f952008-09-13 17:21:40 +02006545
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006546 rtl8169_net_suspend(dev);
6547
Francois Romieucecb5fd2011-04-01 10:21:07 +02006548 /* Restore original MAC address */
Ivan Veceracc098dc2009-11-29 23:12:52 -08006549 rtl_rar_set(tp, dev->perm_addr);
6550
Hayes Wang92fc43b2011-07-06 15:58:03 +08006551 rtl8169_hw_reset(tp);
françois romieu4bb3f522009-06-17 11:41:45 +00006552
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006553 if (system_state == SYSTEM_POWER_OFF) {
David S. Miller1805b2f2011-10-24 18:18:09 -04006554 if (__rtl8169_get_wol(tp) & WAKE_ANY) {
6555 rtl_wol_suspend_quirk(tp);
6556 rtl_wol_shutdown_quirk(tp);
françois romieuca52efd2009-07-24 12:34:19 +00006557 }
6558
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006559 pci_wake_from_d3(pdev, true);
6560 pci_set_power_state(pdev, PCI_D3hot);
6561 }
françois romieu2a15cd22012-03-06 01:14:12 +00006562
6563 pm_runtime_put_noidle(d);
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006564}
Francois Romieu5d06a992006-02-23 00:47:58 +01006565
Bill Pembertonbaf63292012-12-03 09:23:28 -05006566static void rtl_remove_one(struct pci_dev *pdev)
Francois Romieue27566e2012-03-08 09:54:01 +01006567{
6568 struct net_device *dev = pci_get_drvdata(pdev);
6569 struct rtl8169_private *tp = netdev_priv(dev);
6570
6571 if (tp->mac_version == RTL_GIGA_MAC_VER_27 ||
6572 tp->mac_version == RTL_GIGA_MAC_VER_28 ||
6573 tp->mac_version == RTL_GIGA_MAC_VER_31) {
6574 rtl8168_driver_stop(tp);
6575 }
6576
6577 cancel_work_sync(&tp->wk.work);
6578
Devendra Nagaad1be8d2012-05-31 01:51:20 +00006579 netif_napi_del(&tp->napi);
6580
Francois Romieue27566e2012-03-08 09:54:01 +01006581 unregister_netdev(dev);
6582
6583 rtl_release_firmware(tp);
6584
6585 if (pci_dev_run_wake(pdev))
6586 pm_runtime_get_noresume(&pdev->dev);
6587
6588 /* restore original MAC address */
6589 rtl_rar_set(tp, dev->perm_addr);
6590
6591 rtl_disable_msi(pdev, tp);
6592 rtl8169_release_board(pdev, dev, tp->mmio_addr);
6593 pci_set_drvdata(pdev, NULL);
6594}
6595
Francois Romieufa9c3852012-03-08 10:01:50 +01006596static const struct net_device_ops rtl_netdev_ops = {
Francois Romieudf43ac72012-03-08 09:48:40 +01006597 .ndo_open = rtl_open,
Francois Romieufa9c3852012-03-08 10:01:50 +01006598 .ndo_stop = rtl8169_close,
6599 .ndo_get_stats64 = rtl8169_get_stats64,
6600 .ndo_start_xmit = rtl8169_start_xmit,
6601 .ndo_tx_timeout = rtl8169_tx_timeout,
6602 .ndo_validate_addr = eth_validate_addr,
6603 .ndo_change_mtu = rtl8169_change_mtu,
6604 .ndo_fix_features = rtl8169_fix_features,
6605 .ndo_set_features = rtl8169_set_features,
6606 .ndo_set_mac_address = rtl_set_mac_address,
6607 .ndo_do_ioctl = rtl8169_ioctl,
6608 .ndo_set_rx_mode = rtl_set_rx_mode,
6609#ifdef CONFIG_NET_POLL_CONTROLLER
6610 .ndo_poll_controller = rtl8169_netpoll,
6611#endif
6612
6613};
6614
Francois Romieu31fa8b12012-03-08 10:09:40 +01006615static const struct rtl_cfg_info {
6616 void (*hw_start)(struct net_device *);
6617 unsigned int region;
6618 unsigned int align;
6619 u16 event_slow;
6620 unsigned features;
6621 u8 default_ver;
6622} rtl_cfg_infos [] = {
6623 [RTL_CFG_0] = {
6624 .hw_start = rtl_hw_start_8169,
6625 .region = 1,
6626 .align = 0,
6627 .event_slow = SYSErr | LinkChg | RxOverflow | RxFIFOOver,
6628 .features = RTL_FEATURE_GMII,
6629 .default_ver = RTL_GIGA_MAC_VER_01,
6630 },
6631 [RTL_CFG_1] = {
6632 .hw_start = rtl_hw_start_8168,
6633 .region = 2,
6634 .align = 8,
6635 .event_slow = SYSErr | LinkChg | RxOverflow,
6636 .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI,
6637 .default_ver = RTL_GIGA_MAC_VER_11,
6638 },
6639 [RTL_CFG_2] = {
6640 .hw_start = rtl_hw_start_8101,
6641 .region = 2,
6642 .align = 8,
6643 .event_slow = SYSErr | LinkChg | RxOverflow | RxFIFOOver |
6644 PCSTimeout,
6645 .features = RTL_FEATURE_MSI,
6646 .default_ver = RTL_GIGA_MAC_VER_13,
6647 }
6648};
6649
6650/* Cfg9346_Unlock assumed. */
6651static unsigned rtl_try_msi(struct rtl8169_private *tp,
6652 const struct rtl_cfg_info *cfg)
6653{
6654 void __iomem *ioaddr = tp->mmio_addr;
6655 unsigned msi = 0;
6656 u8 cfg2;
6657
6658 cfg2 = RTL_R8(Config2) & ~MSIEnable;
6659 if (cfg->features & RTL_FEATURE_MSI) {
6660 if (pci_enable_msi(tp->pci_dev)) {
6661 netif_info(tp, hw, tp->dev, "no MSI. Back to INTx.\n");
6662 } else {
6663 cfg2 |= MSIEnable;
6664 msi = RTL_FEATURE_MSI;
6665 }
6666 }
6667 if (tp->mac_version <= RTL_GIGA_MAC_VER_06)
6668 RTL_W8(Config2, cfg2);
6669 return msi;
6670}
6671
Hayes Wangc5583862012-07-02 17:23:22 +08006672DECLARE_RTL_COND(rtl_link_list_ready_cond)
6673{
6674 void __iomem *ioaddr = tp->mmio_addr;
6675
6676 return RTL_R8(MCU) & LINK_LIST_RDY;
6677}
6678
6679DECLARE_RTL_COND(rtl_rxtx_empty_cond)
6680{
6681 void __iomem *ioaddr = tp->mmio_addr;
6682
6683 return (RTL_R8(MCU) & RXTX_EMPTY) == RXTX_EMPTY;
6684}
6685
Bill Pembertonbaf63292012-12-03 09:23:28 -05006686static void rtl_hw_init_8168g(struct rtl8169_private *tp)
Hayes Wangc5583862012-07-02 17:23:22 +08006687{
6688 void __iomem *ioaddr = tp->mmio_addr;
6689 u32 data;
6690
6691 tp->ocp_base = OCP_STD_PHY_BASE;
6692
6693 RTL_W32(MISC, RTL_R32(MISC) | RXDV_GATED_EN);
6694
6695 if (!rtl_udelay_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 42))
6696 return;
6697
6698 if (!rtl_udelay_loop_wait_high(tp, &rtl_rxtx_empty_cond, 100, 42))
6699 return;
6700
6701 RTL_W8(ChipCmd, RTL_R8(ChipCmd) & ~(CmdTxEnb | CmdRxEnb));
6702 msleep(1);
6703 RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
6704
Hayes Wang5f8bcce2012-07-10 08:47:05 +02006705 data = r8168_mac_ocp_read(tp, 0xe8de);
Hayes Wangc5583862012-07-02 17:23:22 +08006706 data &= ~(1 << 14);
6707 r8168_mac_ocp_write(tp, 0xe8de, data);
6708
6709 if (!rtl_udelay_loop_wait_high(tp, &rtl_link_list_ready_cond, 100, 42))
6710 return;
6711
Hayes Wang5f8bcce2012-07-10 08:47:05 +02006712 data = r8168_mac_ocp_read(tp, 0xe8de);
Hayes Wangc5583862012-07-02 17:23:22 +08006713 data |= (1 << 15);
6714 r8168_mac_ocp_write(tp, 0xe8de, data);
6715
6716 if (!rtl_udelay_loop_wait_high(tp, &rtl_link_list_ready_cond, 100, 42))
6717 return;
6718}
6719
Bill Pembertonbaf63292012-12-03 09:23:28 -05006720static void rtl_hw_initialize(struct rtl8169_private *tp)
Hayes Wangc5583862012-07-02 17:23:22 +08006721{
6722 switch (tp->mac_version) {
6723 case RTL_GIGA_MAC_VER_40:
6724 case RTL_GIGA_MAC_VER_41:
6725 rtl_hw_init_8168g(tp);
6726 break;
6727
6728 default:
6729 break;
6730 }
6731}
6732
Bill Pembertonbaf63292012-12-03 09:23:28 -05006733static int
Francois Romieu3b6cf252012-03-08 09:59:04 +01006734rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
6735{
6736 const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data;
6737 const unsigned int region = cfg->region;
6738 struct rtl8169_private *tp;
6739 struct mii_if_info *mii;
6740 struct net_device *dev;
6741 void __iomem *ioaddr;
6742 int chipset, i;
6743 int rc;
6744
6745 if (netif_msg_drv(&debug)) {
6746 printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n",
6747 MODULENAME, RTL8169_VERSION);
6748 }
6749
6750 dev = alloc_etherdev(sizeof (*tp));
6751 if (!dev) {
6752 rc = -ENOMEM;
6753 goto out;
6754 }
6755
6756 SET_NETDEV_DEV(dev, &pdev->dev);
Francois Romieufa9c3852012-03-08 10:01:50 +01006757 dev->netdev_ops = &rtl_netdev_ops;
Francois Romieu3b6cf252012-03-08 09:59:04 +01006758 tp = netdev_priv(dev);
6759 tp->dev = dev;
6760 tp->pci_dev = pdev;
6761 tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT);
6762
6763 mii = &tp->mii;
6764 mii->dev = dev;
6765 mii->mdio_read = rtl_mdio_read;
6766 mii->mdio_write = rtl_mdio_write;
6767 mii->phy_id_mask = 0x1f;
6768 mii->reg_num_mask = 0x1f;
6769 mii->supports_gmii = !!(cfg->features & RTL_FEATURE_GMII);
6770
6771 /* disable ASPM completely as that cause random device stop working
6772 * problems as well as full system hangs for some PCIe devices users */
6773 pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
6774 PCIE_LINK_STATE_CLKPM);
6775
6776 /* enable device (incl. PCI PM wakeup and hotplug setup) */
6777 rc = pci_enable_device(pdev);
6778 if (rc < 0) {
6779 netif_err(tp, probe, dev, "enable failure\n");
6780 goto err_out_free_dev_1;
6781 }
6782
6783 if (pci_set_mwi(pdev) < 0)
6784 netif_info(tp, probe, dev, "Mem-Wr-Inval unavailable\n");
6785
6786 /* make sure PCI base addr 1 is MMIO */
6787 if (!(pci_resource_flags(pdev, region) & IORESOURCE_MEM)) {
6788 netif_err(tp, probe, dev,
6789 "region #%d not an MMIO resource, aborting\n",
6790 region);
6791 rc = -ENODEV;
6792 goto err_out_mwi_2;
6793 }
6794
6795 /* check for weird/broken PCI region reporting */
6796 if (pci_resource_len(pdev, region) < R8169_REGS_SIZE) {
6797 netif_err(tp, probe, dev,
6798 "Invalid PCI region size(s), aborting\n");
6799 rc = -ENODEV;
6800 goto err_out_mwi_2;
6801 }
6802
6803 rc = pci_request_regions(pdev, MODULENAME);
6804 if (rc < 0) {
6805 netif_err(tp, probe, dev, "could not request regions\n");
6806 goto err_out_mwi_2;
6807 }
6808
6809 tp->cp_cmd = RxChkSum;
6810
6811 if ((sizeof(dma_addr_t) > 4) &&
6812 !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && use_dac) {
6813 tp->cp_cmd |= PCIDAC;
6814 dev->features |= NETIF_F_HIGHDMA;
6815 } else {
6816 rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
6817 if (rc < 0) {
6818 netif_err(tp, probe, dev, "DMA configuration failed\n");
6819 goto err_out_free_res_3;
6820 }
6821 }
6822
6823 /* ioremap MMIO region */
6824 ioaddr = ioremap(pci_resource_start(pdev, region), R8169_REGS_SIZE);
6825 if (!ioaddr) {
6826 netif_err(tp, probe, dev, "cannot remap MMIO, aborting\n");
6827 rc = -EIO;
6828 goto err_out_free_res_3;
6829 }
6830 tp->mmio_addr = ioaddr;
6831
6832 if (!pci_is_pcie(pdev))
6833 netif_info(tp, probe, dev, "not PCI Express\n");
6834
6835 /* Identify chip attached to board */
6836 rtl8169_get_mac_version(tp, dev, cfg->default_ver);
6837
6838 rtl_init_rxcfg(tp);
6839
6840 rtl_irq_disable(tp);
6841
Hayes Wangc5583862012-07-02 17:23:22 +08006842 rtl_hw_initialize(tp);
6843
Francois Romieu3b6cf252012-03-08 09:59:04 +01006844 rtl_hw_reset(tp);
6845
6846 rtl_ack_events(tp, 0xffff);
6847
6848 pci_set_master(pdev);
6849
6850 /*
6851 * Pretend we are using VLANs; This bypasses a nasty bug where
6852 * Interrupts stop flowing on high load on 8110SCd controllers.
6853 */
6854 if (tp->mac_version == RTL_GIGA_MAC_VER_05)
6855 tp->cp_cmd |= RxVlan;
6856
6857 rtl_init_mdio_ops(tp);
6858 rtl_init_pll_power_ops(tp);
6859 rtl_init_jumbo_ops(tp);
Hayes Wangbeb1fe12012-03-30 14:33:01 +08006860 rtl_init_csi_ops(tp);
Francois Romieu3b6cf252012-03-08 09:59:04 +01006861
6862 rtl8169_print_mac_version(tp);
6863
6864 chipset = tp->mac_version;
6865 tp->txd_version = rtl_chip_infos[chipset].txd_version;
6866
6867 RTL_W8(Cfg9346, Cfg9346_Unlock);
6868 RTL_W8(Config1, RTL_R8(Config1) | PMEnable);
6869 RTL_W8(Config5, RTL_R8(Config5) & PMEStatus);
6870 if ((RTL_R8(Config3) & (LinkUp | MagicPacket)) != 0)
6871 tp->features |= RTL_FEATURE_WOL;
6872 if ((RTL_R8(Config5) & (UWF | BWF | MWF)) != 0)
6873 tp->features |= RTL_FEATURE_WOL;
6874 tp->features |= rtl_try_msi(tp, cfg);
6875 RTL_W8(Cfg9346, Cfg9346_Lock);
6876
6877 if (rtl_tbi_enabled(tp)) {
6878 tp->set_speed = rtl8169_set_speed_tbi;
6879 tp->get_settings = rtl8169_gset_tbi;
6880 tp->phy_reset_enable = rtl8169_tbi_reset_enable;
6881 tp->phy_reset_pending = rtl8169_tbi_reset_pending;
6882 tp->link_ok = rtl8169_tbi_link_ok;
6883 tp->do_ioctl = rtl_tbi_ioctl;
6884 } else {
6885 tp->set_speed = rtl8169_set_speed_xmii;
6886 tp->get_settings = rtl8169_gset_xmii;
6887 tp->phy_reset_enable = rtl8169_xmii_reset_enable;
6888 tp->phy_reset_pending = rtl8169_xmii_reset_pending;
6889 tp->link_ok = rtl8169_xmii_link_ok;
6890 tp->do_ioctl = rtl_xmii_ioctl;
6891 }
6892
6893 mutex_init(&tp->wk.mutex);
6894
6895 /* Get MAC address */
6896 for (i = 0; i < ETH_ALEN; i++)
6897 dev->dev_addr[i] = RTL_R8(MAC0 + i);
Francois Romieu3b6cf252012-03-08 09:59:04 +01006898
6899 SET_ETHTOOL_OPS(dev, &rtl8169_ethtool_ops);
6900 dev->watchdog_timeo = RTL8169_TX_TIMEOUT;
Francois Romieu3b6cf252012-03-08 09:59:04 +01006901
6902 netif_napi_add(dev, &tp->napi, rtl8169_poll, R8169_NAPI_WEIGHT);
6903
6904 /* don't enable SG, IP_CSUM and TSO by default - it might not work
6905 * properly for all devices */
6906 dev->features |= NETIF_F_RXCSUM |
6907 NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
6908
6909 dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
6910 NETIF_F_RXCSUM | NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
6911 dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
6912 NETIF_F_HIGHDMA;
6913
6914 if (tp->mac_version == RTL_GIGA_MAC_VER_05)
6915 /* 8110SCd requires hardware Rx VLAN - disallow toggling */
6916 dev->hw_features &= ~NETIF_F_HW_VLAN_RX;
6917
6918 dev->hw_features |= NETIF_F_RXALL;
6919 dev->hw_features |= NETIF_F_RXFCS;
6920
6921 tp->hw_start = cfg->hw_start;
6922 tp->event_slow = cfg->event_slow;
6923
6924 tp->opts1_mask = (tp->mac_version != RTL_GIGA_MAC_VER_01) ?
6925 ~(RxBOVF | RxFOVF) : ~0;
6926
6927 init_timer(&tp->timer);
6928 tp->timer.data = (unsigned long) dev;
6929 tp->timer.function = rtl8169_phy_timer;
6930
6931 tp->rtl_fw = RTL_FIRMWARE_UNKNOWN;
6932
6933 rc = register_netdev(dev);
6934 if (rc < 0)
6935 goto err_out_msi_4;
6936
6937 pci_set_drvdata(pdev, dev);
6938
Francois Romieu92a7c4e2012-03-10 10:42:12 +01006939 netif_info(tp, probe, dev, "%s at 0x%p, %pM, XID %08x IRQ %d\n",
6940 rtl_chip_infos[chipset].name, ioaddr, dev->dev_addr,
6941 (u32)(RTL_R32(TxConfig) & 0x9cf0f8ff), pdev->irq);
Francois Romieu3b6cf252012-03-08 09:59:04 +01006942 if (rtl_chip_infos[chipset].jumbo_max != JUMBO_1K) {
6943 netif_info(tp, probe, dev, "jumbo features [frames: %d bytes, "
6944 "tx checksumming: %s]\n",
6945 rtl_chip_infos[chipset].jumbo_max,
6946 rtl_chip_infos[chipset].jumbo_tx_csum ? "ok" : "ko");
6947 }
6948
6949 if (tp->mac_version == RTL_GIGA_MAC_VER_27 ||
6950 tp->mac_version == RTL_GIGA_MAC_VER_28 ||
6951 tp->mac_version == RTL_GIGA_MAC_VER_31) {
6952 rtl8168_driver_start(tp);
6953 }
6954
6955 device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL);
6956
6957 if (pci_dev_run_wake(pdev))
6958 pm_runtime_put_noidle(&pdev->dev);
6959
6960 netif_carrier_off(dev);
6961
6962out:
6963 return rc;
6964
6965err_out_msi_4:
Devendra Nagaad1be8d2012-05-31 01:51:20 +00006966 netif_napi_del(&tp->napi);
Francois Romieu3b6cf252012-03-08 09:59:04 +01006967 rtl_disable_msi(pdev, tp);
6968 iounmap(ioaddr);
6969err_out_free_res_3:
6970 pci_release_regions(pdev);
6971err_out_mwi_2:
6972 pci_clear_mwi(pdev);
6973 pci_disable_device(pdev);
6974err_out_free_dev_1:
6975 free_netdev(dev);
6976 goto out;
6977}
6978
Linus Torvalds1da177e2005-04-16 15:20:36 -07006979static struct pci_driver rtl8169_pci_driver = {
6980 .name = MODULENAME,
6981 .id_table = rtl8169_pci_tbl,
Francois Romieu3b6cf252012-03-08 09:59:04 +01006982 .probe = rtl_init_one,
Bill Pembertonbaf63292012-12-03 09:23:28 -05006983 .remove = rtl_remove_one,
Francois Romieu1765f952008-09-13 17:21:40 +02006984 .shutdown = rtl_shutdown,
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006985 .driver.pm = RTL8169_PM_OPS,
Linus Torvalds1da177e2005-04-16 15:20:36 -07006986};
6987
Devendra Naga3eeb7da2012-10-26 09:27:42 +00006988module_pci_driver(rtl8169_pci_driver);