blob: 51c78ce27b37a1c9eeb6a177f5ffb5576c861d56 [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>
Alexey Dobriyana6b7a402011-06-06 10:43:46 +000024#include <linux/interrupt.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070025#include <linux/dma-mapping.h>
Rafael J. Wysockie1759442010-03-14 14:33:51 +000026#include <linux/pm_runtime.h>
françois romieubca03d52011-01-03 15:07:31 +000027#include <linux/firmware.h>
Stanislaw Gruszkaba04c7c2011-02-22 02:00:11 +000028#include <linux/pci-aspm.h>
Paul Gortmaker70c71602011-05-22 16:47:17 -040029#include <linux/prefetch.h>
hayeswange9746042014-07-11 16:25:58 +080030#include <linux/ipv6.h>
31#include <net/ip6_checksum.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070032
33#include <asm/io.h>
34#include <asm/irq.h>
35
Francois Romieu865c6522008-05-11 14:51:00 +020036#define RTL8169_VERSION "2.3LK-NAPI"
Linus Torvalds1da177e2005-04-16 15:20:36 -070037#define MODULENAME "r8169"
38#define PFX MODULENAME ": "
39
françois romieubca03d52011-01-03 15:07:31 +000040#define FIRMWARE_8168D_1 "rtl_nic/rtl8168d-1.fw"
41#define FIRMWARE_8168D_2 "rtl_nic/rtl8168d-2.fw"
hayeswang01dc7fe2011-03-21 01:50:28 +000042#define FIRMWARE_8168E_1 "rtl_nic/rtl8168e-1.fw"
43#define FIRMWARE_8168E_2 "rtl_nic/rtl8168e-2.fw"
Hayes Wang70090422011-07-06 15:58:06 +080044#define FIRMWARE_8168E_3 "rtl_nic/rtl8168e-3.fw"
Hayes Wangc2218922011-09-06 16:55:18 +080045#define FIRMWARE_8168F_1 "rtl_nic/rtl8168f-1.fw"
46#define FIRMWARE_8168F_2 "rtl_nic/rtl8168f-2.fw"
Hayes Wang5a5e4442011-02-22 17:26:21 +080047#define FIRMWARE_8105E_1 "rtl_nic/rtl8105e-1.fw"
Hayes Wang7e18dca2012-03-30 14:33:02 +080048#define FIRMWARE_8402_1 "rtl_nic/rtl8402-1.fw"
Hayes Wangb3d7b2f2012-03-30 14:48:06 +080049#define FIRMWARE_8411_1 "rtl_nic/rtl8411-1.fw"
hayeswang45dd95c2013-07-08 17:09:01 +080050#define FIRMWARE_8411_2 "rtl_nic/rtl8411-2.fw"
Hayes Wang5598bfe2012-07-02 17:23:21 +080051#define FIRMWARE_8106E_1 "rtl_nic/rtl8106e-1.fw"
hayeswang58152cd2013-04-01 22:23:42 +000052#define FIRMWARE_8106E_2 "rtl_nic/rtl8106e-2.fw"
hayeswangbeb330a2013-04-01 22:23:39 +000053#define FIRMWARE_8168G_2 "rtl_nic/rtl8168g-2.fw"
hayeswang57538c42013-04-01 22:23:40 +000054#define FIRMWARE_8168G_3 "rtl_nic/rtl8168g-3.fw"
françois romieubca03d52011-01-03 15:07:31 +000055
Linus Torvalds1da177e2005-04-16 15:20:36 -070056#ifdef RTL8169_DEBUG
57#define assert(expr) \
Francois Romieu5b0384f2006-08-16 16:00:01 +020058 if (!(expr)) { \
59 printk( "Assertion failed! %s,%s,%s,line=%d\n", \
Harvey Harrisonb39d66a2008-08-20 16:52:04 -070060 #expr,__FILE__,__func__,__LINE__); \
Francois Romieu5b0384f2006-08-16 16:00:01 +020061 }
Joe Perches06fa7352007-10-18 21:15:00 +020062#define dprintk(fmt, args...) \
63 do { printk(KERN_DEBUG PFX fmt, ## args); } while (0)
Linus Torvalds1da177e2005-04-16 15:20:36 -070064#else
65#define assert(expr) do {} while (0)
66#define dprintk(fmt, args...) do {} while (0)
67#endif /* RTL8169_DEBUG */
68
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +020069#define R8169_MSG_DEFAULT \
Francois Romieuf0e837d2005-09-30 16:54:02 -070070 (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN)
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +020071
Julien Ducourthial477206a2012-05-09 00:00:06 +020072#define TX_SLOTS_AVAIL(tp) \
73 (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx)
74
75/* A skbuff with nr_frags needs nr_frags+1 entries in the tx queue */
76#define TX_FRAGS_READY_FOR(tp,nr_frags) \
77 (TX_SLOTS_AVAIL(tp) >= (nr_frags + 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -070078
Linus Torvalds1da177e2005-04-16 15:20:36 -070079/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
80 The RTL chips use a 64 element hash table based on the Ethernet CRC. */
Arjan van de Venf71e1302006-03-03 21:33:57 -050081static const int multicast_filter_limit = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -070082
Francois Romieu9c14cea2008-07-05 00:21:15 +020083#define MAX_READ_REQUEST_SHIFT 12
Michal Schmidtaee77e42012-09-09 13:55:26 +000084#define TX_DMA_BURST 7 /* Maximum PCI burst, '7' is unlimited */
Linus Torvalds1da177e2005-04-16 15:20:36 -070085#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */
86
87#define R8169_REGS_SIZE 256
88#define R8169_NAPI_WEIGHT 64
89#define NUM_TX_DESC 64 /* Number of Tx descriptor registers */
Timo Teräs9fba0812013-01-15 21:01:24 +000090#define NUM_RX_DESC 256U /* Number of Rx descriptor registers */
Linus Torvalds1da177e2005-04-16 15:20:36 -070091#define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc))
92#define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc))
93
94#define RTL8169_TX_TIMEOUT (6*HZ)
95#define RTL8169_PHY_TIMEOUT (10*HZ)
96
97/* write/read MMIO register */
98#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg))
99#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg))
100#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg))
101#define RTL_R8(reg) readb (ioaddr + (reg))
102#define RTL_R16(reg) readw (ioaddr + (reg))
Junchang Wang06f555f2010-05-30 02:26:07 +0000103#define RTL_R32(reg) readl (ioaddr + (reg))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104
105enum mac_version {
Francois Romieu85bffe62011-04-27 08:22:39 +0200106 RTL_GIGA_MAC_VER_01 = 0,
107 RTL_GIGA_MAC_VER_02,
108 RTL_GIGA_MAC_VER_03,
109 RTL_GIGA_MAC_VER_04,
110 RTL_GIGA_MAC_VER_05,
111 RTL_GIGA_MAC_VER_06,
112 RTL_GIGA_MAC_VER_07,
113 RTL_GIGA_MAC_VER_08,
114 RTL_GIGA_MAC_VER_09,
115 RTL_GIGA_MAC_VER_10,
116 RTL_GIGA_MAC_VER_11,
117 RTL_GIGA_MAC_VER_12,
118 RTL_GIGA_MAC_VER_13,
119 RTL_GIGA_MAC_VER_14,
120 RTL_GIGA_MAC_VER_15,
121 RTL_GIGA_MAC_VER_16,
122 RTL_GIGA_MAC_VER_17,
123 RTL_GIGA_MAC_VER_18,
124 RTL_GIGA_MAC_VER_19,
125 RTL_GIGA_MAC_VER_20,
126 RTL_GIGA_MAC_VER_21,
127 RTL_GIGA_MAC_VER_22,
128 RTL_GIGA_MAC_VER_23,
129 RTL_GIGA_MAC_VER_24,
130 RTL_GIGA_MAC_VER_25,
131 RTL_GIGA_MAC_VER_26,
132 RTL_GIGA_MAC_VER_27,
133 RTL_GIGA_MAC_VER_28,
134 RTL_GIGA_MAC_VER_29,
135 RTL_GIGA_MAC_VER_30,
136 RTL_GIGA_MAC_VER_31,
137 RTL_GIGA_MAC_VER_32,
138 RTL_GIGA_MAC_VER_33,
Hayes Wang70090422011-07-06 15:58:06 +0800139 RTL_GIGA_MAC_VER_34,
Hayes Wangc2218922011-09-06 16:55:18 +0800140 RTL_GIGA_MAC_VER_35,
141 RTL_GIGA_MAC_VER_36,
Hayes Wang7e18dca2012-03-30 14:33:02 +0800142 RTL_GIGA_MAC_VER_37,
Hayes Wangb3d7b2f2012-03-30 14:48:06 +0800143 RTL_GIGA_MAC_VER_38,
Hayes Wang5598bfe2012-07-02 17:23:21 +0800144 RTL_GIGA_MAC_VER_39,
Hayes Wangc5583862012-07-02 17:23:22 +0800145 RTL_GIGA_MAC_VER_40,
146 RTL_GIGA_MAC_VER_41,
hayeswang57538c42013-04-01 22:23:40 +0000147 RTL_GIGA_MAC_VER_42,
hayeswang58152cd2013-04-01 22:23:42 +0000148 RTL_GIGA_MAC_VER_43,
hayeswang45dd95c2013-07-08 17:09:01 +0800149 RTL_GIGA_MAC_VER_44,
Francois Romieu85bffe62011-04-27 08:22:39 +0200150 RTL_GIGA_MAC_NONE = 0xff,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151};
152
Francois Romieu2b7b4312011-04-18 22:53:24 -0700153enum rtl_tx_desc_version {
154 RTL_TD_0 = 0,
155 RTL_TD_1 = 1,
156};
157
Francois Romieud58d46b2011-05-03 16:38:29 +0200158#define JUMBO_1K ETH_DATA_LEN
159#define JUMBO_4K (4*1024 - ETH_HLEN - 2)
160#define JUMBO_6K (6*1024 - ETH_HLEN - 2)
161#define JUMBO_7K (7*1024 - ETH_HLEN - 2)
162#define JUMBO_9K (9*1024 - ETH_HLEN - 2)
163
164#define _R(NAME,TD,FW,SZ,B) { \
165 .name = NAME, \
166 .txd_version = TD, \
167 .fw_name = FW, \
168 .jumbo_max = SZ, \
169 .jumbo_tx_csum = B \
170}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171
Jesper Juhl3c6bee12006-01-09 20:54:01 -0800172static const struct {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173 const char *name;
Francois Romieu2b7b4312011-04-18 22:53:24 -0700174 enum rtl_tx_desc_version txd_version;
Francois Romieu85bffe62011-04-27 08:22:39 +0200175 const char *fw_name;
Francois Romieud58d46b2011-05-03 16:38:29 +0200176 u16 jumbo_max;
177 bool jumbo_tx_csum;
Francois Romieu85bffe62011-04-27 08:22:39 +0200178} rtl_chip_infos[] = {
179 /* PCI devices. */
180 [RTL_GIGA_MAC_VER_01] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200181 _R("RTL8169", RTL_TD_0, NULL, JUMBO_7K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200182 [RTL_GIGA_MAC_VER_02] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200183 _R("RTL8169s", RTL_TD_0, NULL, JUMBO_7K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200184 [RTL_GIGA_MAC_VER_03] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200185 _R("RTL8110s", RTL_TD_0, NULL, JUMBO_7K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200186 [RTL_GIGA_MAC_VER_04] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200187 _R("RTL8169sb/8110sb", RTL_TD_0, NULL, JUMBO_7K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200188 [RTL_GIGA_MAC_VER_05] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200189 _R("RTL8169sc/8110sc", RTL_TD_0, NULL, JUMBO_7K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200190 [RTL_GIGA_MAC_VER_06] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200191 _R("RTL8169sc/8110sc", RTL_TD_0, NULL, JUMBO_7K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200192 /* PCI-E devices. */
193 [RTL_GIGA_MAC_VER_07] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200194 _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200195 [RTL_GIGA_MAC_VER_08] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200196 _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200197 [RTL_GIGA_MAC_VER_09] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200198 _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200199 [RTL_GIGA_MAC_VER_10] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200200 _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200201 [RTL_GIGA_MAC_VER_11] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200202 _R("RTL8168b/8111b", RTL_TD_0, NULL, JUMBO_4K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200203 [RTL_GIGA_MAC_VER_12] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200204 _R("RTL8168b/8111b", RTL_TD_0, NULL, JUMBO_4K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200205 [RTL_GIGA_MAC_VER_13] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200206 _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200207 [RTL_GIGA_MAC_VER_14] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200208 _R("RTL8100e", RTL_TD_0, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200209 [RTL_GIGA_MAC_VER_15] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200210 _R("RTL8100e", RTL_TD_0, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200211 [RTL_GIGA_MAC_VER_16] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200212 _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200213 [RTL_GIGA_MAC_VER_17] =
hayeswangf75761b2014-03-11 15:11:59 +0800214 _R("RTL8168b/8111b", RTL_TD_0, NULL, JUMBO_4K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200215 [RTL_GIGA_MAC_VER_18] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200216 _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200217 [RTL_GIGA_MAC_VER_19] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200218 _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200219 [RTL_GIGA_MAC_VER_20] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200220 _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200221 [RTL_GIGA_MAC_VER_21] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200222 _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200223 [RTL_GIGA_MAC_VER_22] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200224 _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200225 [RTL_GIGA_MAC_VER_23] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200226 _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200227 [RTL_GIGA_MAC_VER_24] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200228 _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200229 [RTL_GIGA_MAC_VER_25] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200230 _R("RTL8168d/8111d", RTL_TD_1, FIRMWARE_8168D_1,
231 JUMBO_9K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200232 [RTL_GIGA_MAC_VER_26] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200233 _R("RTL8168d/8111d", RTL_TD_1, FIRMWARE_8168D_2,
234 JUMBO_9K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200235 [RTL_GIGA_MAC_VER_27] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200236 _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200237 [RTL_GIGA_MAC_VER_28] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200238 _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200239 [RTL_GIGA_MAC_VER_29] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200240 _R("RTL8105e", RTL_TD_1, FIRMWARE_8105E_1,
241 JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200242 [RTL_GIGA_MAC_VER_30] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200243 _R("RTL8105e", RTL_TD_1, FIRMWARE_8105E_1,
244 JUMBO_1K, true),
Francois Romieu85bffe62011-04-27 08:22:39 +0200245 [RTL_GIGA_MAC_VER_31] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200246 _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200247 [RTL_GIGA_MAC_VER_32] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200248 _R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_1,
249 JUMBO_9K, false),
Francois Romieu85bffe62011-04-27 08:22:39 +0200250 [RTL_GIGA_MAC_VER_33] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200251 _R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_2,
252 JUMBO_9K, false),
Hayes Wang70090422011-07-06 15:58:06 +0800253 [RTL_GIGA_MAC_VER_34] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200254 _R("RTL8168evl/8111evl",RTL_TD_1, FIRMWARE_8168E_3,
255 JUMBO_9K, false),
Hayes Wangc2218922011-09-06 16:55:18 +0800256 [RTL_GIGA_MAC_VER_35] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200257 _R("RTL8168f/8111f", RTL_TD_1, FIRMWARE_8168F_1,
258 JUMBO_9K, false),
Hayes Wangc2218922011-09-06 16:55:18 +0800259 [RTL_GIGA_MAC_VER_36] =
Francois Romieud58d46b2011-05-03 16:38:29 +0200260 _R("RTL8168f/8111f", RTL_TD_1, FIRMWARE_8168F_2,
261 JUMBO_9K, false),
Hayes Wang7e18dca2012-03-30 14:33:02 +0800262 [RTL_GIGA_MAC_VER_37] =
263 _R("RTL8402", RTL_TD_1, FIRMWARE_8402_1,
264 JUMBO_1K, true),
Hayes Wangb3d7b2f2012-03-30 14:48:06 +0800265 [RTL_GIGA_MAC_VER_38] =
266 _R("RTL8411", RTL_TD_1, FIRMWARE_8411_1,
267 JUMBO_9K, false),
Hayes Wang5598bfe2012-07-02 17:23:21 +0800268 [RTL_GIGA_MAC_VER_39] =
269 _R("RTL8106e", RTL_TD_1, FIRMWARE_8106E_1,
270 JUMBO_1K, true),
Hayes Wangc5583862012-07-02 17:23:22 +0800271 [RTL_GIGA_MAC_VER_40] =
hayeswangbeb330a2013-04-01 22:23:39 +0000272 _R("RTL8168g/8111g", RTL_TD_1, FIRMWARE_8168G_2,
Hayes Wangc5583862012-07-02 17:23:22 +0800273 JUMBO_9K, false),
274 [RTL_GIGA_MAC_VER_41] =
275 _R("RTL8168g/8111g", RTL_TD_1, NULL, JUMBO_9K, false),
hayeswang57538c42013-04-01 22:23:40 +0000276 [RTL_GIGA_MAC_VER_42] =
277 _R("RTL8168g/8111g", RTL_TD_1, FIRMWARE_8168G_3,
278 JUMBO_9K, false),
hayeswang58152cd2013-04-01 22:23:42 +0000279 [RTL_GIGA_MAC_VER_43] =
280 _R("RTL8106e", RTL_TD_1, FIRMWARE_8106E_2,
281 JUMBO_1K, true),
hayeswang45dd95c2013-07-08 17:09:01 +0800282 [RTL_GIGA_MAC_VER_44] =
283 _R("RTL8411", RTL_TD_1, FIRMWARE_8411_2,
284 JUMBO_9K, false),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285};
286#undef _R
287
Francois Romieubcf0bf92006-07-26 23:14:13 +0200288enum cfg_version {
289 RTL_CFG_0 = 0x00,
290 RTL_CFG_1,
291 RTL_CFG_2
292};
293
Alexey Dobriyana3aa1882010-01-07 11:58:11 +0000294static DEFINE_PCI_DEVICE_TABLE(rtl8169_pci_tbl) = {
Francois Romieubcf0bf92006-07-26 23:14:13 +0200295 { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 },
Francois Romieud2eed8c2006-08-31 22:01:07 +0200296 { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 },
Francois Romieud81bf552006-09-20 21:31:20 +0200297 { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 },
Francois Romieu07ce4062007-02-23 23:36:39 +0100298 { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 },
Francois Romieubcf0bf92006-07-26 23:14:13 +0200299 { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 },
Francois Romieu2a35cfa2012-08-31 23:06:17 +0200300 { PCI_VENDOR_ID_DLINK, 0x4300,
301 PCI_VENDOR_ID_DLINK, 0x4b10, 0, 0, RTL_CFG_1 },
Francois Romieubcf0bf92006-07-26 23:14:13 +0200302 { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 },
Lennart Sorensen93a3aa22011-07-28 13:18:11 +0000303 { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4302), 0, 0, RTL_CFG_0 },
Francois Romieubc1660b2007-10-12 23:58:09 +0200304 { PCI_DEVICE(PCI_VENDOR_ID_AT, 0xc107), 0, 0, RTL_CFG_0 },
Francois Romieubcf0bf92006-07-26 23:14:13 +0200305 { PCI_DEVICE(0x16ec, 0x0116), 0, 0, RTL_CFG_0 },
306 { PCI_VENDOR_ID_LINKSYS, 0x1032,
307 PCI_ANY_ID, 0x0024, 0, 0, RTL_CFG_0 },
Ciaran McCreesh11d2e282007-11-01 22:48:15 +0100308 { 0x0001, 0x8168,
309 PCI_ANY_ID, 0x2410, 0, 0, RTL_CFG_2 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310 {0,},
311};
312
313MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl);
314
Eric Dumazet6f0333b2010-10-11 11:17:47 +0000315static int rx_buf_sz = 16383;
David S. Miller4300e8c2010-03-26 10:23:30 -0700316static int use_dac;
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +0200317static struct {
318 u32 msg_enable;
319} debug = { -1 };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320
Francois Romieu07d3f512007-02-21 22:40:46 +0100321enum rtl_registers {
322 MAC0 = 0, /* Ethernet hardware address. */
Francois Romieu773d2022007-01-31 23:47:43 +0100323 MAC4 = 4,
Francois Romieu07d3f512007-02-21 22:40:46 +0100324 MAR0 = 8, /* Multicast filter. */
325 CounterAddrLow = 0x10,
326 CounterAddrHigh = 0x14,
327 TxDescStartAddrLow = 0x20,
328 TxDescStartAddrHigh = 0x24,
329 TxHDescStartAddrLow = 0x28,
330 TxHDescStartAddrHigh = 0x2c,
331 FLASH = 0x30,
332 ERSR = 0x36,
333 ChipCmd = 0x37,
334 TxPoll = 0x38,
335 IntrMask = 0x3c,
336 IntrStatus = 0x3e,
Francois Romieu2b7b4312011-04-18 22:53:24 -0700337
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800338 TxConfig = 0x40,
339#define TXCFG_AUTO_FIFO (1 << 7) /* 8111e-vl */
340#define TXCFG_EMPTY (1 << 11) /* 8111e-vl */
341
342 RxConfig = 0x44,
343#define RX128_INT_EN (1 << 15) /* 8111c and later */
344#define RX_MULTI_EN (1 << 14) /* 8111c only */
345#define RXCFG_FIFO_SHIFT 13
346 /* No threshold before first PCI xfer */
347#define RX_FIFO_THRESH (7 << RXCFG_FIFO_SHIFT)
hayeswangbeb330a2013-04-01 22:23:39 +0000348#define RX_EARLY_OFF (1 << 11)
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800349#define RXCFG_DMA_SHIFT 8
350 /* Unlimited maximum PCI burst. */
351#define RX_DMA_BURST (7 << RXCFG_DMA_SHIFT)
Francois Romieu2b7b4312011-04-18 22:53:24 -0700352
Francois Romieu07d3f512007-02-21 22:40:46 +0100353 RxMissed = 0x4c,
354 Cfg9346 = 0x50,
355 Config0 = 0x51,
356 Config1 = 0x52,
357 Config2 = 0x53,
Francois Romieud387b422012-04-17 11:12:01 +0200358#define PME_SIGNAL (1 << 5) /* 8168c and later */
359
Francois Romieu07d3f512007-02-21 22:40:46 +0100360 Config3 = 0x54,
361 Config4 = 0x55,
362 Config5 = 0x56,
363 MultiIntr = 0x5c,
364 PHYAR = 0x60,
Francois Romieu07d3f512007-02-21 22:40:46 +0100365 PHYstatus = 0x6c,
366 RxMaxSize = 0xda,
367 CPlusCmd = 0xe0,
368 IntrMitigate = 0xe2,
369 RxDescAddrLow = 0xe4,
370 RxDescAddrHigh = 0xe8,
françois romieuf0298f82011-01-03 15:07:42 +0000371 EarlyTxThres = 0xec, /* 8169. Unit of 32 bytes. */
372
373#define NoEarlyTx 0x3f /* Max value : no early transmit. */
374
375 MaxTxPacketSize = 0xec, /* 8101/8168. Unit of 128 bytes. */
376
377#define TxPacketMax (8064 >> 7)
Hayes Wang3090bd92011-09-06 16:55:15 +0800378#define EarlySize 0x27
françois romieuf0298f82011-01-03 15:07:42 +0000379
Francois Romieu07d3f512007-02-21 22:40:46 +0100380 FuncEvent = 0xf0,
381 FuncEventMask = 0xf4,
382 FuncPresetState = 0xf8,
383 FuncForceEvent = 0xfc,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384};
385
Francois Romieuf162a5d2008-06-01 22:37:49 +0200386enum rtl8110_registers {
387 TBICSR = 0x64,
388 TBI_ANAR = 0x68,
389 TBI_LPAR = 0x6a,
390};
391
392enum rtl8168_8101_registers {
393 CSIDR = 0x64,
394 CSIAR = 0x68,
395#define CSIAR_FLAG 0x80000000
396#define CSIAR_WRITE_CMD 0x80000000
397#define CSIAR_BYTE_ENABLE 0x0f
398#define CSIAR_BYTE_ENABLE_SHIFT 12
399#define CSIAR_ADDR_MASK 0x0fff
Hayes Wang7e18dca2012-03-30 14:33:02 +0800400#define CSIAR_FUNC_CARD 0x00000000
401#define CSIAR_FUNC_SDIO 0x00010000
402#define CSIAR_FUNC_NIC 0x00020000
hayeswang45dd95c2013-07-08 17:09:01 +0800403#define CSIAR_FUNC_NIC2 0x00010000
françois romieu065c27c2011-01-03 15:08:12 +0000404 PMCH = 0x6f,
Francois Romieuf162a5d2008-06-01 22:37:49 +0200405 EPHYAR = 0x80,
406#define EPHYAR_FLAG 0x80000000
407#define EPHYAR_WRITE_CMD 0x80000000
408#define EPHYAR_REG_MASK 0x1f
409#define EPHYAR_REG_SHIFT 16
410#define EPHYAR_DATA_MASK 0xffff
Hayes Wang5a5e4442011-02-22 17:26:21 +0800411 DLLPR = 0xd0,
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800412#define PFM_EN (1 << 6)
Francois Romieuf162a5d2008-06-01 22:37:49 +0200413 DBG_REG = 0xd1,
414#define FIX_NAK_1 (1 << 4)
415#define FIX_NAK_2 (1 << 3)
Hayes Wang5a5e4442011-02-22 17:26:21 +0800416 TWSI = 0xd2,
417 MCU = 0xd3,
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800418#define NOW_IS_OOB (1 << 7)
Hayes Wangc5583862012-07-02 17:23:22 +0800419#define TX_EMPTY (1 << 5)
420#define RX_EMPTY (1 << 4)
421#define RXTX_EMPTY (TX_EMPTY | RX_EMPTY)
Hayes Wang5a5e4442011-02-22 17:26:21 +0800422#define EN_NDP (1 << 3)
423#define EN_OOB_RESET (1 << 2)
Hayes Wangc5583862012-07-02 17:23:22 +0800424#define LINK_LIST_RDY (1 << 1)
françois romieudaf9df62009-10-07 12:44:20 +0000425 EFUSEAR = 0xdc,
426#define EFUSEAR_FLAG 0x80000000
427#define EFUSEAR_WRITE_CMD 0x80000000
428#define EFUSEAR_READ_CMD 0x00000000
429#define EFUSEAR_REG_MASK 0x03ff
430#define EFUSEAR_REG_SHIFT 8
431#define EFUSEAR_DATA_MASK 0xff
Francois Romieuf162a5d2008-06-01 22:37:49 +0200432};
433
françois romieuc0e45c12011-01-03 15:08:04 +0000434enum rtl8168_registers {
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800435 LED_FREQ = 0x1a,
436 EEE_LED = 0x1b,
françois romieub646d902011-01-03 15:08:21 +0000437 ERIDR = 0x70,
438 ERIAR = 0x74,
439#define ERIAR_FLAG 0x80000000
440#define ERIAR_WRITE_CMD 0x80000000
441#define ERIAR_READ_CMD 0x00000000
442#define ERIAR_ADDR_BYTE_ALIGN 4
françois romieub646d902011-01-03 15:08:21 +0000443#define ERIAR_TYPE_SHIFT 16
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800444#define ERIAR_EXGMAC (0x00 << ERIAR_TYPE_SHIFT)
445#define ERIAR_MSIX (0x01 << ERIAR_TYPE_SHIFT)
446#define ERIAR_ASF (0x02 << ERIAR_TYPE_SHIFT)
447#define ERIAR_MASK_SHIFT 12
448#define ERIAR_MASK_0001 (0x1 << ERIAR_MASK_SHIFT)
449#define ERIAR_MASK_0011 (0x3 << ERIAR_MASK_SHIFT)
Hayes Wangc5583862012-07-02 17:23:22 +0800450#define ERIAR_MASK_0101 (0x5 << ERIAR_MASK_SHIFT)
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800451#define ERIAR_MASK_1111 (0xf << ERIAR_MASK_SHIFT)
françois romieuc0e45c12011-01-03 15:08:04 +0000452 EPHY_RXER_NUM = 0x7c,
453 OCPDR = 0xb0, /* OCP GPHY access */
454#define OCPDR_WRITE_CMD 0x80000000
455#define OCPDR_READ_CMD 0x00000000
456#define OCPDR_REG_MASK 0x7f
457#define OCPDR_GPHY_REG_SHIFT 16
458#define OCPDR_DATA_MASK 0xffff
459 OCPAR = 0xb4,
460#define OCPAR_FLAG 0x80000000
461#define OCPAR_GPHY_WRITE_CMD 0x8000f060
462#define OCPAR_GPHY_READ_CMD 0x0000f060
Hayes Wangc5583862012-07-02 17:23:22 +0800463 GPHY_OCP = 0xb8,
hayeswang01dc7fe2011-03-21 01:50:28 +0000464 RDSAR1 = 0xd0, /* 8168c only. Undocumented on 8168dp */
465 MISC = 0xf0, /* 8168e only. */
Francois Romieucecb5fd2011-04-01 10:21:07 +0200466#define TXPLA_RST (1 << 29)
Hayes Wang5598bfe2012-07-02 17:23:21 +0800467#define DISABLE_LAN_EN (1 << 23) /* Enable GPIO pin */
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800468#define PWM_EN (1 << 22)
Hayes Wangc5583862012-07-02 17:23:22 +0800469#define RXDV_GATED_EN (1 << 19)
Hayes Wang5598bfe2012-07-02 17:23:21 +0800470#define EARLY_TALLY_EN (1 << 16)
françois romieuc0e45c12011-01-03 15:08:04 +0000471};
472
Francois Romieu07d3f512007-02-21 22:40:46 +0100473enum rtl_register_content {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474 /* InterruptStatusBits */
Francois Romieu07d3f512007-02-21 22:40:46 +0100475 SYSErr = 0x8000,
476 PCSTimeout = 0x4000,
477 SWInt = 0x0100,
478 TxDescUnavail = 0x0080,
479 RxFIFOOver = 0x0040,
480 LinkChg = 0x0020,
481 RxOverflow = 0x0010,
482 TxErr = 0x0008,
483 TxOK = 0x0004,
484 RxErr = 0x0002,
485 RxOK = 0x0001,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486
487 /* RxStatusDesc */
David S. Miller8decf862011-09-22 03:23:13 -0400488 RxBOVF = (1 << 24),
Francois Romieu9dccf612006-05-14 12:31:17 +0200489 RxFOVF = (1 << 23),
490 RxRWT = (1 << 22),
491 RxRES = (1 << 21),
492 RxRUNT = (1 << 20),
493 RxCRC = (1 << 19),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494
495 /* ChipCmdBits */
Hayes Wang4f6b00e52011-07-06 15:58:02 +0800496 StopReq = 0x80,
Francois Romieu07d3f512007-02-21 22:40:46 +0100497 CmdReset = 0x10,
498 CmdRxEnb = 0x08,
499 CmdTxEnb = 0x04,
500 RxBufEmpty = 0x01,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501
Francois Romieu275391a2007-02-23 23:50:28 +0100502 /* TXPoll register p.5 */
503 HPQ = 0x80, /* Poll cmd on the high prio queue */
504 NPQ = 0x40, /* Poll cmd on the low prio queue */
505 FSWInt = 0x01, /* Forced software interrupt */
506
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507 /* Cfg9346Bits */
Francois Romieu07d3f512007-02-21 22:40:46 +0100508 Cfg9346_Lock = 0x00,
509 Cfg9346_Unlock = 0xc0,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510
511 /* rx_mode_bits */
Francois Romieu07d3f512007-02-21 22:40:46 +0100512 AcceptErr = 0x20,
513 AcceptRunt = 0x10,
514 AcceptBroadcast = 0x08,
515 AcceptMulticast = 0x04,
516 AcceptMyPhys = 0x02,
517 AcceptAllPhys = 0x01,
Francois Romieu1687b562011-07-19 17:21:29 +0200518#define RX_CONFIG_ACCEPT_MASK 0x3f
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520 /* TxConfigBits */
521 TxInterFrameGapShift = 24,
522 TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */
523
Francois Romieu5d06a992006-02-23 00:47:58 +0100524 /* Config1 register p.24 */
Francois Romieuf162a5d2008-06-01 22:37:49 +0200525 LEDS1 = (1 << 7),
526 LEDS0 = (1 << 6),
Francois Romieuf162a5d2008-06-01 22:37:49 +0200527 Speed_down = (1 << 4),
528 MEMMAP = (1 << 3),
529 IOMAP = (1 << 2),
530 VPD = (1 << 1),
Francois Romieu5d06a992006-02-23 00:47:58 +0100531 PMEnable = (1 << 0), /* Power Management Enable */
532
Francois Romieu6dccd162007-02-13 23:38:05 +0100533 /* Config2 register p. 25 */
hayeswang57538c42013-04-01 22:23:40 +0000534 ClkReqEn = (1 << 7), /* Clock Request Enable */
françois romieu2ca6cf02011-12-15 08:37:43 +0000535 MSIEnable = (1 << 5), /* 8169 only. Reserved in the 8168. */
Francois Romieu6dccd162007-02-13 23:38:05 +0100536 PCI_Clock_66MHz = 0x01,
537 PCI_Clock_33MHz = 0x00,
538
Francois Romieu61a4dcc2006-02-23 00:55:25 +0100539 /* Config3 register p.25 */
540 MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */
541 LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */
Francois Romieud58d46b2011-05-03 16:38:29 +0200542 Jumbo_En0 = (1 << 2), /* 8168 only. Reserved in the 8168b */
Francois Romieuf162a5d2008-06-01 22:37:49 +0200543 Beacon_en = (1 << 0), /* 8168 only. Reserved in the 8168b */
Francois Romieu61a4dcc2006-02-23 00:55:25 +0100544
Francois Romieud58d46b2011-05-03 16:38:29 +0200545 /* Config4 register */
546 Jumbo_En1 = (1 << 1), /* 8168 only. Reserved in the 8168b */
547
Francois Romieu5d06a992006-02-23 00:47:58 +0100548 /* Config5 register p.27 */
Francois Romieu61a4dcc2006-02-23 00:55:25 +0100549 BWF = (1 << 6), /* Accept Broadcast wakeup frame */
550 MWF = (1 << 5), /* Accept Multicast wakeup frame */
551 UWF = (1 << 4), /* Accept Unicast wakeup frame */
Francois Romieucecb5fd2011-04-01 10:21:07 +0200552 Spi_en = (1 << 3),
Francois Romieu61a4dcc2006-02-23 00:55:25 +0100553 LanWake = (1 << 1), /* LanWake enable/disable */
Francois Romieu5d06a992006-02-23 00:47:58 +0100554 PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */
hayeswang57538c42013-04-01 22:23:40 +0000555 ASPM_en = (1 << 0), /* ASPM enable */
Francois Romieu5d06a992006-02-23 00:47:58 +0100556
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557 /* TBICSR p.28 */
558 TBIReset = 0x80000000,
559 TBILoopback = 0x40000000,
560 TBINwEnable = 0x20000000,
561 TBINwRestart = 0x10000000,
562 TBILinkOk = 0x02000000,
563 TBINwComplete = 0x01000000,
564
565 /* CPlusCmd p.31 */
Francois Romieuf162a5d2008-06-01 22:37:49 +0200566 EnableBist = (1 << 15), // 8168 8101
567 Mac_dbgo_oe = (1 << 14), // 8168 8101
568 Normal_mode = (1 << 13), // unused
569 Force_half_dup = (1 << 12), // 8168 8101
570 Force_rxflow_en = (1 << 11), // 8168 8101
571 Force_txflow_en = (1 << 10), // 8168 8101
572 Cxpl_dbg_sel = (1 << 9), // 8168 8101
573 ASF = (1 << 8), // 8168 8101
574 PktCntrDisable = (1 << 7), // 8168 8101
575 Mac_dbgo_sel = 0x001c, // 8168
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576 RxVlan = (1 << 6),
577 RxChkSum = (1 << 5),
578 PCIDAC = (1 << 4),
579 PCIMulRW = (1 << 3),
Francois Romieu0e485152007-02-20 00:00:26 +0100580 INTT_0 = 0x0000, // 8168
581 INTT_1 = 0x0001, // 8168
582 INTT_2 = 0x0002, // 8168
583 INTT_3 = 0x0003, // 8168
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584
585 /* rtl8169_PHYstatus */
Francois Romieu07d3f512007-02-21 22:40:46 +0100586 TBI_Enable = 0x80,
587 TxFlowCtrl = 0x40,
588 RxFlowCtrl = 0x20,
589 _1000bpsF = 0x10,
590 _100bps = 0x08,
591 _10bps = 0x04,
592 LinkStatus = 0x02,
593 FullDup = 0x01,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595 /* _TBICSRBit */
Francois Romieu07d3f512007-02-21 22:40:46 +0100596 TBILinkOK = 0x02000000,
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +0200597
598 /* DumpCounterCommand */
Francois Romieu07d3f512007-02-21 22:40:46 +0100599 CounterDump = 0x8,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600};
601
Francois Romieu2b7b4312011-04-18 22:53:24 -0700602enum rtl_desc_bit {
603 /* First doubleword. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604 DescOwn = (1 << 31), /* Descriptor is owned by NIC */
605 RingEnd = (1 << 30), /* End of descriptor ring */
606 FirstFrag = (1 << 29), /* First segment of a packet */
607 LastFrag = (1 << 28), /* Final segment of a packet */
Francois Romieu2b7b4312011-04-18 22:53:24 -0700608};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609
Francois Romieu2b7b4312011-04-18 22:53:24 -0700610/* Generic case. */
611enum rtl_tx_desc_bit {
612 /* First doubleword. */
613 TD_LSO = (1 << 27), /* Large Send Offload */
614#define TD_MSS_MAX 0x07ffu /* MSS value */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615
Francois Romieu2b7b4312011-04-18 22:53:24 -0700616 /* Second doubleword. */
617 TxVlanTag = (1 << 17), /* Add VLAN tag */
618};
619
620/* 8169, 8168b and 810x except 8102e. */
621enum rtl_tx_desc_bit_0 {
622 /* First doubleword. */
623#define TD0_MSS_SHIFT 16 /* MSS position (11 bits) */
624 TD0_TCP_CS = (1 << 16), /* Calculate TCP/IP checksum */
625 TD0_UDP_CS = (1 << 17), /* Calculate UDP/IP checksum */
626 TD0_IP_CS = (1 << 18), /* Calculate IP checksum */
627};
628
629/* 8102e, 8168c and beyond. */
630enum rtl_tx_desc_bit_1 {
hayeswangbdfa4ed2014-07-11 16:25:57 +0800631 /* First doubleword. */
632 TD1_GTSENV4 = (1 << 26), /* Giant Send for IPv4 */
hayeswange9746042014-07-11 16:25:58 +0800633 TD1_GTSENV6 = (1 << 25), /* Giant Send for IPv6 */
hayeswangbdfa4ed2014-07-11 16:25:57 +0800634#define GTTCPHO_SHIFT 18
hayeswange9746042014-07-11 16:25:58 +0800635#define GTTCPHO_MAX 0x7fU
hayeswangbdfa4ed2014-07-11 16:25:57 +0800636
Francois Romieu2b7b4312011-04-18 22:53:24 -0700637 /* Second doubleword. */
hayeswange9746042014-07-11 16:25:58 +0800638#define TCPHO_SHIFT 18
639#define TCPHO_MAX 0x3ffU
Francois Romieu2b7b4312011-04-18 22:53:24 -0700640#define TD1_MSS_SHIFT 18 /* MSS position (11 bits) */
hayeswange9746042014-07-11 16:25:58 +0800641 TD1_IPv6_CS = (1 << 28), /* Calculate IPv6 checksum */
642 TD1_IPv4_CS = (1 << 29), /* Calculate IPv4 checksum */
Francois Romieu2b7b4312011-04-18 22:53:24 -0700643 TD1_TCP_CS = (1 << 30), /* Calculate TCP/IP checksum */
644 TD1_UDP_CS = (1 << 31), /* Calculate UDP/IP checksum */
645};
646
Francois Romieu2b7b4312011-04-18 22:53:24 -0700647enum rtl_rx_desc_bit {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648 /* Rx private */
649 PID1 = (1 << 18), /* Protocol ID bit 1/2 */
650 PID0 = (1 << 17), /* Protocol ID bit 2/2 */
651
652#define RxProtoUDP (PID1)
653#define RxProtoTCP (PID0)
654#define RxProtoIP (PID1 | PID0)
655#define RxProtoMask RxProtoIP
656
657 IPFail = (1 << 16), /* IP checksum failed */
658 UDPFail = (1 << 15), /* UDP/IP checksum failed */
659 TCPFail = (1 << 14), /* TCP/IP checksum failed */
660 RxVlanTag = (1 << 16), /* VLAN tag available */
661};
662
663#define RsvdMask 0x3fffc000
664
665struct TxDesc {
Rolf Eike Beer6cccd6e2007-05-21 22:11:04 +0200666 __le32 opts1;
667 __le32 opts2;
668 __le64 addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669};
670
671struct RxDesc {
Rolf Eike Beer6cccd6e2007-05-21 22:11:04 +0200672 __le32 opts1;
673 __le32 opts2;
674 __le64 addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675};
676
677struct ring_info {
678 struct sk_buff *skb;
679 u32 len;
680 u8 __pad[sizeof(void *) - sizeof(u32)];
681};
682
Francois Romieuf23e7fd2007-10-04 22:36:14 +0200683enum features {
Francois Romieuccdffb92008-07-26 14:26:06 +0200684 RTL_FEATURE_WOL = (1 << 0),
685 RTL_FEATURE_MSI = (1 << 1),
686 RTL_FEATURE_GMII = (1 << 2),
Francois Romieuf23e7fd2007-10-04 22:36:14 +0200687};
688
Ivan Vecera355423d2009-02-06 21:49:57 -0800689struct rtl8169_counters {
690 __le64 tx_packets;
691 __le64 rx_packets;
692 __le64 tx_errors;
693 __le32 rx_errors;
694 __le16 rx_missed;
695 __le16 align_errors;
696 __le32 tx_one_collision;
697 __le32 tx_multi_collision;
698 __le64 rx_unicast;
699 __le64 rx_broadcast;
700 __le32 rx_multicast;
701 __le16 tx_aborted;
702 __le16 tx_underun;
703};
704
Francois Romieuda78dbf2012-01-26 14:18:23 +0100705enum rtl_flag {
Francois Romieu6c4a70c2012-01-31 10:56:44 +0100706 RTL_FLAG_TASK_ENABLED,
Francois Romieuda78dbf2012-01-26 14:18:23 +0100707 RTL_FLAG_TASK_SLOW_PENDING,
708 RTL_FLAG_TASK_RESET_PENDING,
709 RTL_FLAG_TASK_PHY_PENDING,
710 RTL_FLAG_MAX
711};
712
Junchang Wang8027aa22012-03-04 23:30:32 +0100713struct rtl8169_stats {
714 u64 packets;
715 u64 bytes;
716 struct u64_stats_sync syncp;
717};
718
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719struct rtl8169_private {
720 void __iomem *mmio_addr; /* memory map physical address */
Francois Romieucecb5fd2011-04-01 10:21:07 +0200721 struct pci_dev *pci_dev;
David Howellsc4028952006-11-22 14:57:56 +0000722 struct net_device *dev;
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700723 struct napi_struct napi;
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +0200724 u32 msg_enable;
Francois Romieu2b7b4312011-04-18 22:53:24 -0700725 u16 txd_version;
726 u16 mac_version;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727 u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */
728 u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729 u32 dirty_tx;
Junchang Wang8027aa22012-03-04 23:30:32 +0100730 struct rtl8169_stats rx_stats;
731 struct rtl8169_stats tx_stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732 struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */
733 struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */
734 dma_addr_t TxPhyAddr;
735 dma_addr_t RxPhyAddr;
Eric Dumazet6f0333b2010-10-11 11:17:47 +0000736 void *Rx_databuff[NUM_RX_DESC]; /* Rx data buffers */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737 struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738 struct timer_list timer;
739 u16 cp_cmd;
Francois Romieuda78dbf2012-01-26 14:18:23 +0100740
741 u16 event_slow;
françois romieuc0e45c12011-01-03 15:08:04 +0000742
743 struct mdio_ops {
Francois Romieu24192212012-07-06 20:19:42 +0200744 void (*write)(struct rtl8169_private *, int, int);
745 int (*read)(struct rtl8169_private *, int);
françois romieuc0e45c12011-01-03 15:08:04 +0000746 } mdio_ops;
747
françois romieu065c27c2011-01-03 15:08:12 +0000748 struct pll_power_ops {
749 void (*down)(struct rtl8169_private *);
750 void (*up)(struct rtl8169_private *);
751 } pll_power_ops;
752
Francois Romieud58d46b2011-05-03 16:38:29 +0200753 struct jumbo_ops {
754 void (*enable)(struct rtl8169_private *);
755 void (*disable)(struct rtl8169_private *);
756 } jumbo_ops;
757
Hayes Wangbeb1fe12012-03-30 14:33:01 +0800758 struct csi_ops {
Francois Romieu52989f02012-07-06 13:37:00 +0200759 void (*write)(struct rtl8169_private *, int, int);
760 u32 (*read)(struct rtl8169_private *, int);
Hayes Wangbeb1fe12012-03-30 14:33:01 +0800761 } csi_ops;
762
Oliver Neukum54405cd2011-01-06 21:55:13 +0100763 int (*set_speed)(struct net_device *, u8 aneg, u16 sp, u8 dpx, u32 adv);
Francois Romieuccdffb92008-07-26 14:26:06 +0200764 int (*get_settings)(struct net_device *, struct ethtool_cmd *);
françois romieu4da19632011-01-03 15:07:55 +0000765 void (*phy_reset_enable)(struct rtl8169_private *tp);
Francois Romieu07ce4062007-02-23 23:36:39 +0100766 void (*hw_start)(struct net_device *);
françois romieu4da19632011-01-03 15:07:55 +0000767 unsigned int (*phy_reset_pending)(struct rtl8169_private *tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768 unsigned int (*link_ok)(void __iomem *);
Francois Romieu8b4ab282008-11-19 22:05:25 -0800769 int (*do_ioctl)(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd);
hayeswang5888d3f2014-07-11 16:25:56 +0800770 bool (*tso_csum)(struct rtl8169_private *, struct sk_buff *, u32 *);
Francois Romieu4422bcd2012-01-26 11:23:32 +0100771
772 struct {
Francois Romieuda78dbf2012-01-26 14:18:23 +0100773 DECLARE_BITMAP(flags, RTL_FLAG_MAX);
774 struct mutex mutex;
Francois Romieu4422bcd2012-01-26 11:23:32 +0100775 struct work_struct work;
776 } wk;
777
Francois Romieuf23e7fd2007-10-04 22:36:14 +0200778 unsigned features;
Francois Romieuccdffb92008-07-26 14:26:06 +0200779
780 struct mii_if_info mii;
Ivan Vecera355423d2009-02-06 21:49:57 -0800781 struct rtl8169_counters counters;
Rafael J. Wysockie1759442010-03-14 14:33:51 +0000782 u32 saved_wolopts;
David S. Miller8decf862011-09-22 03:23:13 -0400783 u32 opts1_mask;
françois romieuf1e02ed2011-01-13 13:07:53 +0000784
Francois Romieub6ffd972011-06-17 17:00:05 +0200785 struct rtl_fw {
786 const struct firmware *fw;
Francois Romieu1c361ef2011-06-17 17:16:24 +0200787
788#define RTL_VER_SIZE 32
789
790 char version[RTL_VER_SIZE];
791
792 struct rtl_fw_phy_action {
793 __le32 *code;
794 size_t size;
795 } phy_action;
Francois Romieub6ffd972011-06-17 17:00:05 +0200796 } *rtl_fw;
Phil Carmody497888c2011-07-14 15:07:13 +0300797#define RTL_FIRMWARE_UNKNOWN ERR_PTR(-EAGAIN)
Hayes Wangc5583862012-07-02 17:23:22 +0800798
799 u32 ocp_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800};
801
Ralf Baechle979b6c12005-06-13 14:30:40 -0700802MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804module_param(use_dac, int, 0);
David S. Miller4300e8c2010-03-26 10:23:30 -0700805MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot.");
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +0200806module_param_named(debug, debug.msg_enable, int, 0);
807MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808MODULE_LICENSE("GPL");
809MODULE_VERSION(RTL8169_VERSION);
françois romieubca03d52011-01-03 15:07:31 +0000810MODULE_FIRMWARE(FIRMWARE_8168D_1);
811MODULE_FIRMWARE(FIRMWARE_8168D_2);
hayeswang01dc7fe2011-03-21 01:50:28 +0000812MODULE_FIRMWARE(FIRMWARE_8168E_1);
813MODULE_FIRMWARE(FIRMWARE_8168E_2);
David S. Miller8decf862011-09-22 03:23:13 -0400814MODULE_FIRMWARE(FIRMWARE_8168E_3);
Hayes Wang5a5e4442011-02-22 17:26:21 +0800815MODULE_FIRMWARE(FIRMWARE_8105E_1);
Hayes Wangc2218922011-09-06 16:55:18 +0800816MODULE_FIRMWARE(FIRMWARE_8168F_1);
817MODULE_FIRMWARE(FIRMWARE_8168F_2);
Hayes Wang7e18dca2012-03-30 14:33:02 +0800818MODULE_FIRMWARE(FIRMWARE_8402_1);
Hayes Wangb3d7b2f2012-03-30 14:48:06 +0800819MODULE_FIRMWARE(FIRMWARE_8411_1);
hayeswang45dd95c2013-07-08 17:09:01 +0800820MODULE_FIRMWARE(FIRMWARE_8411_2);
Hayes Wang5598bfe2012-07-02 17:23:21 +0800821MODULE_FIRMWARE(FIRMWARE_8106E_1);
hayeswang58152cd2013-04-01 22:23:42 +0000822MODULE_FIRMWARE(FIRMWARE_8106E_2);
hayeswangbeb330a2013-04-01 22:23:39 +0000823MODULE_FIRMWARE(FIRMWARE_8168G_2);
hayeswang57538c42013-04-01 22:23:40 +0000824MODULE_FIRMWARE(FIRMWARE_8168G_3);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825
Francois Romieuda78dbf2012-01-26 14:18:23 +0100826static void rtl_lock_work(struct rtl8169_private *tp)
827{
828 mutex_lock(&tp->wk.mutex);
829}
830
831static void rtl_unlock_work(struct rtl8169_private *tp)
832{
833 mutex_unlock(&tp->wk.mutex);
834}
835
Francois Romieud58d46b2011-05-03 16:38:29 +0200836static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force)
837{
Jiang Liu7d7903b2012-07-24 17:20:16 +0800838 pcie_capability_clear_and_set_word(pdev, PCI_EXP_DEVCTL,
839 PCI_EXP_DEVCTL_READRQ, force);
Francois Romieud58d46b2011-05-03 16:38:29 +0200840}
841
Francois Romieuffc46952012-07-06 14:19:23 +0200842struct rtl_cond {
843 bool (*check)(struct rtl8169_private *);
844 const char *msg;
845};
846
847static void rtl_udelay(unsigned int d)
848{
849 udelay(d);
850}
851
852static bool rtl_loop_wait(struct rtl8169_private *tp, const struct rtl_cond *c,
853 void (*delay)(unsigned int), unsigned int d, int n,
854 bool high)
855{
856 int i;
857
858 for (i = 0; i < n; i++) {
859 delay(d);
860 if (c->check(tp) == high)
861 return true;
862 }
Francois Romieu82e316e2012-07-11 23:39:51 +0200863 netif_err(tp, drv, tp->dev, "%s == %d (loop: %d, delay: %d).\n",
864 c->msg, !high, n, d);
Francois Romieuffc46952012-07-06 14:19:23 +0200865 return false;
866}
867
868static bool rtl_udelay_loop_wait_high(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, true);
873}
874
875static bool rtl_udelay_loop_wait_low(struct rtl8169_private *tp,
876 const struct rtl_cond *c,
877 unsigned int d, int n)
878{
879 return rtl_loop_wait(tp, c, rtl_udelay, d, n, false);
880}
881
882static bool rtl_msleep_loop_wait_high(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, true);
887}
888
889static bool rtl_msleep_loop_wait_low(struct rtl8169_private *tp,
890 const struct rtl_cond *c,
891 unsigned int d, int n)
892{
893 return rtl_loop_wait(tp, c, msleep, d, n, false);
894}
895
896#define DECLARE_RTL_COND(name) \
897static bool name ## _check(struct rtl8169_private *); \
898 \
899static const struct rtl_cond name = { \
900 .check = name ## _check, \
901 .msg = #name \
902}; \
903 \
904static bool name ## _check(struct rtl8169_private *tp)
905
906DECLARE_RTL_COND(rtl_ocpar_cond)
907{
908 void __iomem *ioaddr = tp->mmio_addr;
909
910 return RTL_R32(OCPAR) & OCPAR_FLAG;
911}
912
françois romieub646d902011-01-03 15:08:21 +0000913static u32 ocp_read(struct rtl8169_private *tp, u8 mask, u16 reg)
914{
915 void __iomem *ioaddr = tp->mmio_addr;
françois romieub646d902011-01-03 15:08:21 +0000916
917 RTL_W32(OCPAR, ((u32)mask & 0x0f) << 12 | (reg & 0x0fff));
Francois Romieuffc46952012-07-06 14:19:23 +0200918
919 return rtl_udelay_loop_wait_high(tp, &rtl_ocpar_cond, 100, 20) ?
920 RTL_R32(OCPDR) : ~0;
françois romieub646d902011-01-03 15:08:21 +0000921}
922
923static void ocp_write(struct rtl8169_private *tp, u8 mask, u16 reg, u32 data)
924{
925 void __iomem *ioaddr = tp->mmio_addr;
françois romieub646d902011-01-03 15:08:21 +0000926
927 RTL_W32(OCPDR, data);
928 RTL_W32(OCPAR, OCPAR_FLAG | ((u32)mask & 0x0f) << 12 | (reg & 0x0fff));
Francois Romieuffc46952012-07-06 14:19:23 +0200929
930 rtl_udelay_loop_wait_low(tp, &rtl_ocpar_cond, 100, 20);
931}
932
933DECLARE_RTL_COND(rtl_eriar_cond)
934{
935 void __iomem *ioaddr = tp->mmio_addr;
936
937 return RTL_R32(ERIAR) & ERIAR_FLAG;
françois romieub646d902011-01-03 15:08:21 +0000938}
939
Hayes Wangfac5b3c2011-02-22 17:26:20 +0800940static void rtl8168_oob_notify(struct rtl8169_private *tp, u8 cmd)
françois romieub646d902011-01-03 15:08:21 +0000941{
Hayes Wangfac5b3c2011-02-22 17:26:20 +0800942 void __iomem *ioaddr = tp->mmio_addr;
françois romieub646d902011-01-03 15:08:21 +0000943
944 RTL_W8(ERIDR, cmd);
945 RTL_W32(ERIAR, 0x800010e8);
946 msleep(2);
Francois Romieuffc46952012-07-06 14:19:23 +0200947
948 if (!rtl_udelay_loop_wait_low(tp, &rtl_eriar_cond, 100, 5))
949 return;
françois romieub646d902011-01-03 15:08:21 +0000950
Hayes Wangfac5b3c2011-02-22 17:26:20 +0800951 ocp_write(tp, 0x1, 0x30, 0x00000001);
françois romieub646d902011-01-03 15:08:21 +0000952}
953
954#define OOB_CMD_RESET 0x00
955#define OOB_CMD_DRIVER_START 0x05
956#define OOB_CMD_DRIVER_STOP 0x06
957
Francois Romieucecb5fd2011-04-01 10:21:07 +0200958static u16 rtl8168_get_ocp_reg(struct rtl8169_private *tp)
959{
960 return (tp->mac_version == RTL_GIGA_MAC_VER_31) ? 0xb8 : 0x10;
961}
962
Francois Romieuffc46952012-07-06 14:19:23 +0200963DECLARE_RTL_COND(rtl_ocp_read_cond)
françois romieub646d902011-01-03 15:08:21 +0000964{
Francois Romieucecb5fd2011-04-01 10:21:07 +0200965 u16 reg;
françois romieub646d902011-01-03 15:08:21 +0000966
Francois Romieucecb5fd2011-04-01 10:21:07 +0200967 reg = rtl8168_get_ocp_reg(tp);
hayeswang4804b3b2011-03-21 01:50:29 +0000968
Francois Romieuffc46952012-07-06 14:19:23 +0200969 return ocp_read(tp, 0x0f, reg) & 0x00000800;
970}
971
972static void rtl8168_driver_start(struct rtl8169_private *tp)
973{
974 rtl8168_oob_notify(tp, OOB_CMD_DRIVER_START);
975
976 rtl_msleep_loop_wait_high(tp, &rtl_ocp_read_cond, 10, 10);
françois romieub646d902011-01-03 15:08:21 +0000977}
978
979static void rtl8168_driver_stop(struct rtl8169_private *tp)
980{
françois romieub646d902011-01-03 15:08:21 +0000981 rtl8168_oob_notify(tp, OOB_CMD_DRIVER_STOP);
982
Francois Romieuffc46952012-07-06 14:19:23 +0200983 rtl_msleep_loop_wait_low(tp, &rtl_ocp_read_cond, 10, 10);
françois romieub646d902011-01-03 15:08:21 +0000984}
985
hayeswang4804b3b2011-03-21 01:50:29 +0000986static int r8168dp_check_dash(struct rtl8169_private *tp)
987{
Francois Romieucecb5fd2011-04-01 10:21:07 +0200988 u16 reg = rtl8168_get_ocp_reg(tp);
hayeswang4804b3b2011-03-21 01:50:29 +0000989
Francois Romieucecb5fd2011-04-01 10:21:07 +0200990 return (ocp_read(tp, 0x0f, reg) & 0x00008000) ? 1 : 0;
hayeswang4804b3b2011-03-21 01:50:29 +0000991}
françois romieub646d902011-01-03 15:08:21 +0000992
Hayes Wangc5583862012-07-02 17:23:22 +0800993static bool rtl_ocp_reg_failure(struct rtl8169_private *tp, u32 reg)
994{
995 if (reg & 0xffff0001) {
996 netif_err(tp, drv, tp->dev, "Invalid ocp reg %x!\n", reg);
997 return true;
998 }
999 return false;
1000}
1001
1002DECLARE_RTL_COND(rtl_ocp_gphy_cond)
1003{
1004 void __iomem *ioaddr = tp->mmio_addr;
1005
1006 return RTL_R32(GPHY_OCP) & OCPAR_FLAG;
1007}
1008
1009static void r8168_phy_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)
1010{
1011 void __iomem *ioaddr = tp->mmio_addr;
1012
1013 if (rtl_ocp_reg_failure(tp, reg))
1014 return;
1015
1016 RTL_W32(GPHY_OCP, OCPAR_FLAG | (reg << 15) | data);
1017
1018 rtl_udelay_loop_wait_low(tp, &rtl_ocp_gphy_cond, 25, 10);
1019}
1020
1021static u16 r8168_phy_ocp_read(struct rtl8169_private *tp, u32 reg)
1022{
1023 void __iomem *ioaddr = tp->mmio_addr;
1024
1025 if (rtl_ocp_reg_failure(tp, reg))
1026 return 0;
1027
1028 RTL_W32(GPHY_OCP, reg << 15);
1029
1030 return rtl_udelay_loop_wait_high(tp, &rtl_ocp_gphy_cond, 25, 10) ?
1031 (RTL_R32(GPHY_OCP) & 0xffff) : ~0;
1032}
1033
Hayes Wangc5583862012-07-02 17:23:22 +08001034static void r8168_mac_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)
1035{
1036 void __iomem *ioaddr = tp->mmio_addr;
1037
1038 if (rtl_ocp_reg_failure(tp, reg))
1039 return;
1040
1041 RTL_W32(OCPDR, OCPAR_FLAG | (reg << 15) | data);
Hayes Wangc5583862012-07-02 17:23:22 +08001042}
1043
1044static u16 r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg)
1045{
1046 void __iomem *ioaddr = tp->mmio_addr;
1047
1048 if (rtl_ocp_reg_failure(tp, reg))
1049 return 0;
1050
1051 RTL_W32(OCPDR, reg << 15);
1052
Hayes Wang3a83ad12012-07-11 20:31:56 +08001053 return RTL_R32(OCPDR);
Hayes Wangc5583862012-07-02 17:23:22 +08001054}
1055
1056#define OCP_STD_PHY_BASE 0xa400
1057
1058static void r8168g_mdio_write(struct rtl8169_private *tp, int reg, int value)
1059{
1060 if (reg == 0x1f) {
1061 tp->ocp_base = value ? value << 4 : OCP_STD_PHY_BASE;
1062 return;
1063 }
1064
1065 if (tp->ocp_base != OCP_STD_PHY_BASE)
1066 reg -= 0x10;
1067
1068 r8168_phy_ocp_write(tp, tp->ocp_base + reg * 2, value);
1069}
1070
1071static int r8168g_mdio_read(struct rtl8169_private *tp, int reg)
1072{
1073 if (tp->ocp_base != OCP_STD_PHY_BASE)
1074 reg -= 0x10;
1075
1076 return r8168_phy_ocp_read(tp, tp->ocp_base + reg * 2);
1077}
1078
hayeswangeee37862013-04-01 22:23:38 +00001079static void mac_mcu_write(struct rtl8169_private *tp, int reg, int value)
1080{
1081 if (reg == 0x1f) {
1082 tp->ocp_base = value << 4;
1083 return;
1084 }
1085
1086 r8168_mac_ocp_write(tp, tp->ocp_base + reg, value);
1087}
1088
1089static int mac_mcu_read(struct rtl8169_private *tp, int reg)
1090{
1091 return r8168_mac_ocp_read(tp, tp->ocp_base + reg);
1092}
1093
Francois Romieuffc46952012-07-06 14:19:23 +02001094DECLARE_RTL_COND(rtl_phyar_cond)
1095{
1096 void __iomem *ioaddr = tp->mmio_addr;
1097
1098 return RTL_R32(PHYAR) & 0x80000000;
1099}
1100
Francois Romieu24192212012-07-06 20:19:42 +02001101static void r8169_mdio_write(struct rtl8169_private *tp, int reg, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102{
Francois Romieu24192212012-07-06 20:19:42 +02001103 void __iomem *ioaddr = tp->mmio_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104
Francois Romieu24192212012-07-06 20:19:42 +02001105 RTL_W32(PHYAR, 0x80000000 | (reg & 0x1f) << 16 | (value & 0xffff));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106
Francois Romieuffc46952012-07-06 14:19:23 +02001107 rtl_udelay_loop_wait_low(tp, &rtl_phyar_cond, 25, 20);
Timo Teräs024a07b2010-06-06 15:38:47 -07001108 /*
Timo Teräs81a95f02010-06-09 17:31:48 -07001109 * According to hardware specs a 20us delay is required after write
1110 * complete indication, but before sending next command.
Timo Teräs024a07b2010-06-06 15:38:47 -07001111 */
Timo Teräs81a95f02010-06-09 17:31:48 -07001112 udelay(20);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113}
1114
Francois Romieu24192212012-07-06 20:19:42 +02001115static int r8169_mdio_read(struct rtl8169_private *tp, int reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116{
Francois Romieu24192212012-07-06 20:19:42 +02001117 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieuffc46952012-07-06 14:19:23 +02001118 int value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119
Francois Romieu24192212012-07-06 20:19:42 +02001120 RTL_W32(PHYAR, 0x0 | (reg & 0x1f) << 16);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121
Francois Romieuffc46952012-07-06 14:19:23 +02001122 value = rtl_udelay_loop_wait_high(tp, &rtl_phyar_cond, 25, 20) ?
1123 RTL_R32(PHYAR) & 0xffff : ~0;
1124
Timo Teräs81a95f02010-06-09 17:31:48 -07001125 /*
1126 * According to hardware specs a 20us delay is required after read
1127 * complete indication, but before sending next command.
1128 */
1129 udelay(20);
1130
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131 return value;
1132}
1133
Francois Romieu24192212012-07-06 20:19:42 +02001134static void r8168dp_1_mdio_access(struct rtl8169_private *tp, int reg, u32 data)
françois romieuc0e45c12011-01-03 15:08:04 +00001135{
Francois Romieu24192212012-07-06 20:19:42 +02001136 void __iomem *ioaddr = tp->mmio_addr;
françois romieuc0e45c12011-01-03 15:08:04 +00001137
Francois Romieu24192212012-07-06 20:19:42 +02001138 RTL_W32(OCPDR, data | ((reg & OCPDR_REG_MASK) << OCPDR_GPHY_REG_SHIFT));
françois romieuc0e45c12011-01-03 15:08:04 +00001139 RTL_W32(OCPAR, OCPAR_GPHY_WRITE_CMD);
1140 RTL_W32(EPHY_RXER_NUM, 0);
1141
Francois Romieuffc46952012-07-06 14:19:23 +02001142 rtl_udelay_loop_wait_low(tp, &rtl_ocpar_cond, 1000, 100);
françois romieuc0e45c12011-01-03 15:08:04 +00001143}
1144
Francois Romieu24192212012-07-06 20:19:42 +02001145static void r8168dp_1_mdio_write(struct rtl8169_private *tp, int reg, int value)
françois romieuc0e45c12011-01-03 15:08:04 +00001146{
Francois Romieu24192212012-07-06 20:19:42 +02001147 r8168dp_1_mdio_access(tp, reg,
1148 OCPDR_WRITE_CMD | (value & OCPDR_DATA_MASK));
françois romieuc0e45c12011-01-03 15:08:04 +00001149}
1150
Francois Romieu24192212012-07-06 20:19:42 +02001151static int r8168dp_1_mdio_read(struct rtl8169_private *tp, int reg)
françois romieuc0e45c12011-01-03 15:08:04 +00001152{
Francois Romieu24192212012-07-06 20:19:42 +02001153 void __iomem *ioaddr = tp->mmio_addr;
françois romieuc0e45c12011-01-03 15:08:04 +00001154
Francois Romieu24192212012-07-06 20:19:42 +02001155 r8168dp_1_mdio_access(tp, reg, OCPDR_READ_CMD);
françois romieuc0e45c12011-01-03 15:08:04 +00001156
1157 mdelay(1);
1158 RTL_W32(OCPAR, OCPAR_GPHY_READ_CMD);
1159 RTL_W32(EPHY_RXER_NUM, 0);
1160
Francois Romieuffc46952012-07-06 14:19:23 +02001161 return rtl_udelay_loop_wait_high(tp, &rtl_ocpar_cond, 1000, 100) ?
1162 RTL_R32(OCPDR) & OCPDR_DATA_MASK : ~0;
françois romieuc0e45c12011-01-03 15:08:04 +00001163}
1164
françois romieue6de30d2011-01-03 15:08:37 +00001165#define R8168DP_1_MDIO_ACCESS_BIT 0x00020000
1166
1167static void r8168dp_2_mdio_start(void __iomem *ioaddr)
1168{
1169 RTL_W32(0xd0, RTL_R32(0xd0) & ~R8168DP_1_MDIO_ACCESS_BIT);
1170}
1171
1172static void r8168dp_2_mdio_stop(void __iomem *ioaddr)
1173{
1174 RTL_W32(0xd0, RTL_R32(0xd0) | R8168DP_1_MDIO_ACCESS_BIT);
1175}
1176
Francois Romieu24192212012-07-06 20:19:42 +02001177static void r8168dp_2_mdio_write(struct rtl8169_private *tp, int reg, int value)
françois romieue6de30d2011-01-03 15:08:37 +00001178{
Francois Romieu24192212012-07-06 20:19:42 +02001179 void __iomem *ioaddr = tp->mmio_addr;
1180
françois romieue6de30d2011-01-03 15:08:37 +00001181 r8168dp_2_mdio_start(ioaddr);
1182
Francois Romieu24192212012-07-06 20:19:42 +02001183 r8169_mdio_write(tp, reg, value);
françois romieue6de30d2011-01-03 15:08:37 +00001184
1185 r8168dp_2_mdio_stop(ioaddr);
1186}
1187
Francois Romieu24192212012-07-06 20:19:42 +02001188static int r8168dp_2_mdio_read(struct rtl8169_private *tp, int reg)
françois romieue6de30d2011-01-03 15:08:37 +00001189{
Francois Romieu24192212012-07-06 20:19:42 +02001190 void __iomem *ioaddr = tp->mmio_addr;
françois romieue6de30d2011-01-03 15:08:37 +00001191 int value;
1192
1193 r8168dp_2_mdio_start(ioaddr);
1194
Francois Romieu24192212012-07-06 20:19:42 +02001195 value = r8169_mdio_read(tp, reg);
françois romieue6de30d2011-01-03 15:08:37 +00001196
1197 r8168dp_2_mdio_stop(ioaddr);
1198
1199 return value;
1200}
1201
françois romieu4da19632011-01-03 15:07:55 +00001202static void rtl_writephy(struct rtl8169_private *tp, int location, u32 val)
Francois Romieudacf8152008-08-02 20:44:13 +02001203{
Francois Romieu24192212012-07-06 20:19:42 +02001204 tp->mdio_ops.write(tp, location, val);
Francois Romieudacf8152008-08-02 20:44:13 +02001205}
1206
françois romieu4da19632011-01-03 15:07:55 +00001207static int rtl_readphy(struct rtl8169_private *tp, int location)
1208{
Francois Romieu24192212012-07-06 20:19:42 +02001209 return tp->mdio_ops.read(tp, location);
françois romieu4da19632011-01-03 15:07:55 +00001210}
1211
1212static void rtl_patchphy(struct rtl8169_private *tp, int reg_addr, int value)
1213{
1214 rtl_writephy(tp, reg_addr, rtl_readphy(tp, reg_addr) | value);
1215}
1216
1217static void rtl_w1w0_phy(struct rtl8169_private *tp, int reg_addr, int p, int m)
françois romieudaf9df62009-10-07 12:44:20 +00001218{
1219 int val;
1220
françois romieu4da19632011-01-03 15:07:55 +00001221 val = rtl_readphy(tp, reg_addr);
1222 rtl_writephy(tp, reg_addr, (val | p) & ~m);
françois romieudaf9df62009-10-07 12:44:20 +00001223}
1224
Francois Romieuccdffb92008-07-26 14:26:06 +02001225static void rtl_mdio_write(struct net_device *dev, int phy_id, int location,
1226 int val)
1227{
1228 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieuccdffb92008-07-26 14:26:06 +02001229
françois romieu4da19632011-01-03 15:07:55 +00001230 rtl_writephy(tp, location, val);
Francois Romieuccdffb92008-07-26 14:26:06 +02001231}
1232
1233static int rtl_mdio_read(struct net_device *dev, int phy_id, int location)
1234{
1235 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieuccdffb92008-07-26 14:26:06 +02001236
françois romieu4da19632011-01-03 15:07:55 +00001237 return rtl_readphy(tp, location);
Francois Romieuccdffb92008-07-26 14:26:06 +02001238}
1239
Francois Romieuffc46952012-07-06 14:19:23 +02001240DECLARE_RTL_COND(rtl_ephyar_cond)
1241{
1242 void __iomem *ioaddr = tp->mmio_addr;
1243
1244 return RTL_R32(EPHYAR) & EPHYAR_FLAG;
1245}
1246
Francois Romieufdf6fc02012-07-06 22:40:38 +02001247static void rtl_ephy_write(struct rtl8169_private *tp, int reg_addr, int value)
Francois Romieudacf8152008-08-02 20:44:13 +02001248{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001249 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieudacf8152008-08-02 20:44:13 +02001250
1251 RTL_W32(EPHYAR, EPHYAR_WRITE_CMD | (value & EPHYAR_DATA_MASK) |
1252 (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT);
1253
Francois Romieuffc46952012-07-06 14:19:23 +02001254 rtl_udelay_loop_wait_low(tp, &rtl_ephyar_cond, 10, 100);
1255
1256 udelay(10);
Francois Romieudacf8152008-08-02 20:44:13 +02001257}
1258
Francois Romieufdf6fc02012-07-06 22:40:38 +02001259static u16 rtl_ephy_read(struct rtl8169_private *tp, int reg_addr)
Francois Romieudacf8152008-08-02 20:44:13 +02001260{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001261 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieudacf8152008-08-02 20:44:13 +02001262
1263 RTL_W32(EPHYAR, (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT);
1264
Francois Romieuffc46952012-07-06 14:19:23 +02001265 return rtl_udelay_loop_wait_high(tp, &rtl_ephyar_cond, 10, 100) ?
1266 RTL_R32(EPHYAR) & EPHYAR_DATA_MASK : ~0;
Francois Romieudacf8152008-08-02 20:44:13 +02001267}
1268
Francois Romieufdf6fc02012-07-06 22:40:38 +02001269static void rtl_eri_write(struct rtl8169_private *tp, int addr, u32 mask,
1270 u32 val, int type)
Hayes Wang133ac402011-07-06 15:58:05 +08001271{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001272 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang133ac402011-07-06 15:58:05 +08001273
1274 BUG_ON((addr & 3) || (mask == 0));
1275 RTL_W32(ERIDR, val);
1276 RTL_W32(ERIAR, ERIAR_WRITE_CMD | type | mask | addr);
1277
Francois Romieuffc46952012-07-06 14:19:23 +02001278 rtl_udelay_loop_wait_low(tp, &rtl_eriar_cond, 100, 100);
Hayes Wang133ac402011-07-06 15:58:05 +08001279}
1280
Francois Romieufdf6fc02012-07-06 22:40:38 +02001281static u32 rtl_eri_read(struct rtl8169_private *tp, int addr, int type)
Hayes Wang133ac402011-07-06 15:58:05 +08001282{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001283 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang133ac402011-07-06 15:58:05 +08001284
1285 RTL_W32(ERIAR, ERIAR_READ_CMD | type | ERIAR_MASK_1111 | addr);
1286
Francois Romieuffc46952012-07-06 14:19:23 +02001287 return rtl_udelay_loop_wait_high(tp, &rtl_eriar_cond, 100, 100) ?
1288 RTL_R32(ERIDR) : ~0;
Hayes Wang133ac402011-07-06 15:58:05 +08001289}
1290
Francois Romieufdf6fc02012-07-06 22:40:38 +02001291static void rtl_w1w0_eri(struct rtl8169_private *tp, int addr, u32 mask, u32 p,
1292 u32 m, int type)
Hayes Wang133ac402011-07-06 15:58:05 +08001293{
1294 u32 val;
1295
Francois Romieufdf6fc02012-07-06 22:40:38 +02001296 val = rtl_eri_read(tp, addr, type);
1297 rtl_eri_write(tp, addr, mask, (val & ~m) | p, type);
Hayes Wang133ac402011-07-06 15:58:05 +08001298}
1299
françois romieuc28aa382011-08-02 03:53:43 +00001300struct exgmac_reg {
1301 u16 addr;
1302 u16 mask;
1303 u32 val;
1304};
1305
Francois Romieufdf6fc02012-07-06 22:40:38 +02001306static void rtl_write_exgmac_batch(struct rtl8169_private *tp,
françois romieuc28aa382011-08-02 03:53:43 +00001307 const struct exgmac_reg *r, int len)
1308{
1309 while (len-- > 0) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001310 rtl_eri_write(tp, r->addr, r->mask, r->val, ERIAR_EXGMAC);
françois romieuc28aa382011-08-02 03:53:43 +00001311 r++;
1312 }
1313}
1314
Francois Romieuffc46952012-07-06 14:19:23 +02001315DECLARE_RTL_COND(rtl_efusear_cond)
1316{
1317 void __iomem *ioaddr = tp->mmio_addr;
1318
1319 return RTL_R32(EFUSEAR) & EFUSEAR_FLAG;
1320}
1321
Francois Romieufdf6fc02012-07-06 22:40:38 +02001322static u8 rtl8168d_efuse_read(struct rtl8169_private *tp, int reg_addr)
françois romieudaf9df62009-10-07 12:44:20 +00001323{
Francois Romieufdf6fc02012-07-06 22:40:38 +02001324 void __iomem *ioaddr = tp->mmio_addr;
françois romieudaf9df62009-10-07 12:44:20 +00001325
1326 RTL_W32(EFUSEAR, (reg_addr & EFUSEAR_REG_MASK) << EFUSEAR_REG_SHIFT);
1327
Francois Romieuffc46952012-07-06 14:19:23 +02001328 return rtl_udelay_loop_wait_high(tp, &rtl_efusear_cond, 100, 300) ?
1329 RTL_R32(EFUSEAR) & EFUSEAR_DATA_MASK : ~0;
françois romieudaf9df62009-10-07 12:44:20 +00001330}
1331
Francois Romieu9085cdfa2012-01-26 12:59:08 +01001332static u16 rtl_get_events(struct rtl8169_private *tp)
1333{
1334 void __iomem *ioaddr = tp->mmio_addr;
1335
1336 return RTL_R16(IntrStatus);
1337}
1338
1339static void rtl_ack_events(struct rtl8169_private *tp, u16 bits)
1340{
1341 void __iomem *ioaddr = tp->mmio_addr;
1342
1343 RTL_W16(IntrStatus, bits);
1344 mmiowb();
1345}
1346
1347static void rtl_irq_disable(struct rtl8169_private *tp)
1348{
1349 void __iomem *ioaddr = tp->mmio_addr;
1350
1351 RTL_W16(IntrMask, 0);
1352 mmiowb();
1353}
1354
Francois Romieu3e990ff2012-01-26 12:50:01 +01001355static void rtl_irq_enable(struct rtl8169_private *tp, u16 bits)
1356{
1357 void __iomem *ioaddr = tp->mmio_addr;
1358
1359 RTL_W16(IntrMask, bits);
1360}
1361
Francois Romieuda78dbf2012-01-26 14:18:23 +01001362#define RTL_EVENT_NAPI_RX (RxOK | RxErr)
1363#define RTL_EVENT_NAPI_TX (TxOK | TxErr)
1364#define RTL_EVENT_NAPI (RTL_EVENT_NAPI_RX | RTL_EVENT_NAPI_TX)
1365
1366static void rtl_irq_enable_all(struct rtl8169_private *tp)
1367{
1368 rtl_irq_enable(tp, RTL_EVENT_NAPI | tp->event_slow);
1369}
1370
françois romieu811fd302011-12-04 20:30:45 +00001371static void rtl8169_irq_mask_and_ack(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372{
françois romieu811fd302011-12-04 20:30:45 +00001373 void __iomem *ioaddr = tp->mmio_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374
Francois Romieu9085cdfa2012-01-26 12:59:08 +01001375 rtl_irq_disable(tp);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001376 rtl_ack_events(tp, RTL_EVENT_NAPI | tp->event_slow);
françois romieu811fd302011-12-04 20:30:45 +00001377 RTL_R8(ChipCmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378}
1379
françois romieu4da19632011-01-03 15:07:55 +00001380static unsigned int rtl8169_tbi_reset_pending(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381{
françois romieu4da19632011-01-03 15:07:55 +00001382 void __iomem *ioaddr = tp->mmio_addr;
1383
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384 return RTL_R32(TBICSR) & TBIReset;
1385}
1386
françois romieu4da19632011-01-03 15:07:55 +00001387static unsigned int rtl8169_xmii_reset_pending(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388{
françois romieu4da19632011-01-03 15:07:55 +00001389 return rtl_readphy(tp, MII_BMCR) & BMCR_RESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390}
1391
1392static unsigned int rtl8169_tbi_link_ok(void __iomem *ioaddr)
1393{
1394 return RTL_R32(TBICSR) & TBILinkOk;
1395}
1396
1397static unsigned int rtl8169_xmii_link_ok(void __iomem *ioaddr)
1398{
1399 return RTL_R8(PHYstatus) & LinkStatus;
1400}
1401
françois romieu4da19632011-01-03 15:07:55 +00001402static void rtl8169_tbi_reset_enable(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403{
françois romieu4da19632011-01-03 15:07:55 +00001404 void __iomem *ioaddr = tp->mmio_addr;
1405
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406 RTL_W32(TBICSR, RTL_R32(TBICSR) | TBIReset);
1407}
1408
françois romieu4da19632011-01-03 15:07:55 +00001409static void rtl8169_xmii_reset_enable(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410{
1411 unsigned int val;
1412
françois romieu4da19632011-01-03 15:07:55 +00001413 val = rtl_readphy(tp, MII_BMCR) | BMCR_RESET;
1414 rtl_writephy(tp, MII_BMCR, val & 0xffff);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415}
1416
Hayes Wang70090422011-07-06 15:58:06 +08001417static void rtl_link_chg_patch(struct rtl8169_private *tp)
1418{
1419 void __iomem *ioaddr = tp->mmio_addr;
1420 struct net_device *dev = tp->dev;
1421
1422 if (!netif_running(dev))
1423 return;
1424
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08001425 if (tp->mac_version == RTL_GIGA_MAC_VER_34 ||
1426 tp->mac_version == RTL_GIGA_MAC_VER_38) {
Hayes Wang70090422011-07-06 15:58:06 +08001427 if (RTL_R8(PHYstatus) & _1000bpsF) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001428 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x00000011,
1429 ERIAR_EXGMAC);
1430 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005,
1431 ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08001432 } else if (RTL_R8(PHYstatus) & _100bps) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001433 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f,
1434 ERIAR_EXGMAC);
1435 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005,
1436 ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08001437 } else {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001438 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f,
1439 ERIAR_EXGMAC);
1440 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x0000003f,
1441 ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08001442 }
1443 /* Reset packet filter */
Francois Romieufdf6fc02012-07-06 22:40:38 +02001444 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01,
Hayes Wang70090422011-07-06 15:58:06 +08001445 ERIAR_EXGMAC);
Francois Romieufdf6fc02012-07-06 22:40:38 +02001446 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00,
Hayes Wang70090422011-07-06 15:58:06 +08001447 ERIAR_EXGMAC);
Hayes Wangc2218922011-09-06 16:55:18 +08001448 } else if (tp->mac_version == RTL_GIGA_MAC_VER_35 ||
1449 tp->mac_version == RTL_GIGA_MAC_VER_36) {
1450 if (RTL_R8(PHYstatus) & _1000bpsF) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001451 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x00000011,
1452 ERIAR_EXGMAC);
1453 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005,
1454 ERIAR_EXGMAC);
Hayes Wangc2218922011-09-06 16:55:18 +08001455 } else {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001456 rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f,
1457 ERIAR_EXGMAC);
1458 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x0000003f,
1459 ERIAR_EXGMAC);
Hayes Wangc2218922011-09-06 16:55:18 +08001460 }
Hayes Wang7e18dca2012-03-30 14:33:02 +08001461 } else if (tp->mac_version == RTL_GIGA_MAC_VER_37) {
1462 if (RTL_R8(PHYstatus) & _10bps) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001463 rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x4d02,
1464 ERIAR_EXGMAC);
1465 rtl_eri_write(tp, 0x1dc, ERIAR_MASK_0011, 0x0060,
1466 ERIAR_EXGMAC);
Hayes Wang7e18dca2012-03-30 14:33:02 +08001467 } else {
Francois Romieufdf6fc02012-07-06 22:40:38 +02001468 rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000,
1469 ERIAR_EXGMAC);
Hayes Wang7e18dca2012-03-30 14:33:02 +08001470 }
Hayes Wang70090422011-07-06 15:58:06 +08001471 }
1472}
1473
Rafael J. Wysockie4fbce72010-12-08 15:32:14 +00001474static void __rtl8169_check_link_status(struct net_device *dev,
Francois Romieucecb5fd2011-04-01 10:21:07 +02001475 struct rtl8169_private *tp,
1476 void __iomem *ioaddr, bool pm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478 if (tp->link_ok(ioaddr)) {
Hayes Wang70090422011-07-06 15:58:06 +08001479 rtl_link_chg_patch(tp);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001480 /* This is to cancel a scheduled suspend if there's one. */
Rafael J. Wysockie4fbce72010-12-08 15:32:14 +00001481 if (pm)
1482 pm_request_resume(&tp->pci_dev->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483 netif_carrier_on(dev);
Francois Romieu1519e572011-02-03 12:02:36 +01001484 if (net_ratelimit())
1485 netif_info(tp, ifup, dev, "link up\n");
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +02001486 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487 netif_carrier_off(dev);
Joe Perchesbf82c182010-02-09 11:49:50 +00001488 netif_info(tp, ifdown, dev, "link down\n");
Rafael J. Wysockie4fbce72010-12-08 15:32:14 +00001489 if (pm)
hayeswang10953db2011-11-07 20:44:37 +00001490 pm_schedule_suspend(&tp->pci_dev->dev, 5000);
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +02001491 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492}
1493
Rafael J. Wysockie4fbce72010-12-08 15:32:14 +00001494static void rtl8169_check_link_status(struct net_device *dev,
1495 struct rtl8169_private *tp,
1496 void __iomem *ioaddr)
1497{
1498 __rtl8169_check_link_status(dev, tp, ioaddr, false);
1499}
1500
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001501#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST)
1502
1503static u32 __rtl8169_get_wol(struct rtl8169_private *tp)
1504{
1505 void __iomem *ioaddr = tp->mmio_addr;
1506 u8 options;
1507 u32 wolopts = 0;
1508
1509 options = RTL_R8(Config1);
1510 if (!(options & PMEnable))
1511 return 0;
1512
1513 options = RTL_R8(Config3);
1514 if (options & LinkUp)
1515 wolopts |= WAKE_PHY;
1516 if (options & MagicPacket)
1517 wolopts |= WAKE_MAGIC;
1518
1519 options = RTL_R8(Config5);
1520 if (options & UWF)
1521 wolopts |= WAKE_UCAST;
1522 if (options & BWF)
1523 wolopts |= WAKE_BCAST;
1524 if (options & MWF)
1525 wolopts |= WAKE_MCAST;
1526
1527 return wolopts;
1528}
1529
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001530static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
1531{
1532 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001533
Francois Romieuda78dbf2012-01-26 14:18:23 +01001534 rtl_lock_work(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001535
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001536 wol->supported = WAKE_ANY;
1537 wol->wolopts = __rtl8169_get_wol(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001538
Francois Romieuda78dbf2012-01-26 14:18:23 +01001539 rtl_unlock_work(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001540}
1541
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001542static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001543{
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001544 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu07d3f512007-02-21 22:40:46 +01001545 unsigned int i;
Alexey Dobriyan350f7592009-11-25 15:54:21 -08001546 static const struct {
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001547 u32 opt;
1548 u16 reg;
1549 u8 mask;
1550 } cfg[] = {
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001551 { WAKE_PHY, Config3, LinkUp },
1552 { WAKE_MAGIC, Config3, MagicPacket },
1553 { WAKE_UCAST, Config5, UWF },
1554 { WAKE_BCAST, Config5, BWF },
1555 { WAKE_MCAST, Config5, MWF },
1556 { WAKE_ANY, Config5, LanWake }
1557 };
Francois Romieu851e6022012-04-17 11:10:11 +02001558 u8 options;
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001559
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001560 RTL_W8(Cfg9346, Cfg9346_Unlock);
1561
1562 for (i = 0; i < ARRAY_SIZE(cfg); i++) {
Francois Romieu851e6022012-04-17 11:10:11 +02001563 options = RTL_R8(cfg[i].reg) & ~cfg[i].mask;
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001564 if (wolopts & cfg[i].opt)
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001565 options |= cfg[i].mask;
1566 RTL_W8(cfg[i].reg, options);
1567 }
1568
Francois Romieu851e6022012-04-17 11:10:11 +02001569 switch (tp->mac_version) {
1570 case RTL_GIGA_MAC_VER_01 ... RTL_GIGA_MAC_VER_17:
1571 options = RTL_R8(Config1) & ~PMEnable;
1572 if (wolopts)
1573 options |= PMEnable;
1574 RTL_W8(Config1, options);
1575 break;
1576 default:
Francois Romieud387b422012-04-17 11:12:01 +02001577 options = RTL_R8(Config2) & ~PME_SIGNAL;
1578 if (wolopts)
1579 options |= PME_SIGNAL;
1580 RTL_W8(Config2, options);
Francois Romieu851e6022012-04-17 11:10:11 +02001581 break;
1582 }
1583
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001584 RTL_W8(Cfg9346, Cfg9346_Lock);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001585}
1586
1587static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
1588{
1589 struct rtl8169_private *tp = netdev_priv(dev);
1590
Francois Romieuda78dbf2012-01-26 14:18:23 +01001591 rtl_lock_work(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001592
Francois Romieuf23e7fd2007-10-04 22:36:14 +02001593 if (wol->wolopts)
1594 tp->features |= RTL_FEATURE_WOL;
1595 else
1596 tp->features &= ~RTL_FEATURE_WOL;
Rafael J. Wysockie1759442010-03-14 14:33:51 +00001597 __rtl8169_set_wol(tp, wol->wolopts);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001598
1599 rtl_unlock_work(tp);
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001600
françois romieuea809072010-11-08 13:23:58 +00001601 device_set_wakeup_enable(&tp->pci_dev->dev, wol->wolopts);
1602
Francois Romieu61a4dcc2006-02-23 00:55:25 +01001603 return 0;
1604}
1605
Francois Romieu31bd2042011-04-26 18:58:59 +02001606static const char *rtl_lookup_firmware_name(struct rtl8169_private *tp)
1607{
Francois Romieu85bffe62011-04-27 08:22:39 +02001608 return rtl_chip_infos[tp->mac_version].fw_name;
Francois Romieu31bd2042011-04-26 18:58:59 +02001609}
1610
Linus Torvalds1da177e2005-04-16 15:20:36 -07001611static void rtl8169_get_drvinfo(struct net_device *dev,
1612 struct ethtool_drvinfo *info)
1613{
1614 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieub6ffd972011-06-17 17:00:05 +02001615 struct rtl_fw *rtl_fw = tp->rtl_fw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616
Rick Jones68aad782011-11-07 13:29:27 +00001617 strlcpy(info->driver, MODULENAME, sizeof(info->driver));
1618 strlcpy(info->version, RTL8169_VERSION, sizeof(info->version));
1619 strlcpy(info->bus_info, pci_name(tp->pci_dev), sizeof(info->bus_info));
Francois Romieu1c361ef2011-06-17 17:16:24 +02001620 BUILD_BUG_ON(sizeof(info->fw_version) < sizeof(rtl_fw->version));
Rick Jones8ac72d12011-11-22 14:06:26 +00001621 if (!IS_ERR_OR_NULL(rtl_fw))
1622 strlcpy(info->fw_version, rtl_fw->version,
1623 sizeof(info->fw_version));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624}
1625
1626static int rtl8169_get_regs_len(struct net_device *dev)
1627{
1628 return R8169_REGS_SIZE;
1629}
1630
1631static int rtl8169_set_speed_tbi(struct net_device *dev,
Oliver Neukum54405cd2011-01-06 21:55:13 +01001632 u8 autoneg, u16 speed, u8 duplex, u32 ignored)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633{
1634 struct rtl8169_private *tp = netdev_priv(dev);
1635 void __iomem *ioaddr = tp->mmio_addr;
1636 int ret = 0;
1637 u32 reg;
1638
1639 reg = RTL_R32(TBICSR);
1640 if ((autoneg == AUTONEG_DISABLE) && (speed == SPEED_1000) &&
1641 (duplex == DUPLEX_FULL)) {
1642 RTL_W32(TBICSR, reg & ~(TBINwEnable | TBINwRestart));
1643 } else if (autoneg == AUTONEG_ENABLE)
1644 RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart);
1645 else {
Joe Perchesbf82c182010-02-09 11:49:50 +00001646 netif_warn(tp, link, dev,
1647 "incorrect speed setting refused in TBI mode\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001648 ret = -EOPNOTSUPP;
1649 }
1650
1651 return ret;
1652}
1653
1654static int rtl8169_set_speed_xmii(struct net_device *dev,
Oliver Neukum54405cd2011-01-06 21:55:13 +01001655 u8 autoneg, u16 speed, u8 duplex, u32 adv)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001656{
1657 struct rtl8169_private *tp = netdev_priv(dev);
françois romieu3577aa12009-05-19 10:46:48 +00001658 int giga_ctrl, bmcr;
Oliver Neukum54405cd2011-01-06 21:55:13 +01001659 int rc = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660
Hayes Wang716b50a2011-02-22 17:26:18 +08001661 rtl_writephy(tp, 0x1f, 0x0000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662
1663 if (autoneg == AUTONEG_ENABLE) {
françois romieu3577aa12009-05-19 10:46:48 +00001664 int auto_nego;
1665
françois romieu4da19632011-01-03 15:07:55 +00001666 auto_nego = rtl_readphy(tp, MII_ADVERTISE);
Oliver Neukum54405cd2011-01-06 21:55:13 +01001667 auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL |
1668 ADVERTISE_100HALF | ADVERTISE_100FULL);
1669
1670 if (adv & ADVERTISED_10baseT_Half)
1671 auto_nego |= ADVERTISE_10HALF;
1672 if (adv & ADVERTISED_10baseT_Full)
1673 auto_nego |= ADVERTISE_10FULL;
1674 if (adv & ADVERTISED_100baseT_Half)
1675 auto_nego |= ADVERTISE_100HALF;
1676 if (adv & ADVERTISED_100baseT_Full)
1677 auto_nego |= ADVERTISE_100FULL;
1678
françois romieu3577aa12009-05-19 10:46:48 +00001679 auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
1680
françois romieu4da19632011-01-03 15:07:55 +00001681 giga_ctrl = rtl_readphy(tp, MII_CTRL1000);
françois romieu3577aa12009-05-19 10:46:48 +00001682 giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
1683
1684 /* The 8100e/8101e/8102e do Fast Ethernet only. */
Francois Romieu826e6cb2011-03-11 20:30:24 +01001685 if (tp->mii.supports_gmii) {
Oliver Neukum54405cd2011-01-06 21:55:13 +01001686 if (adv & ADVERTISED_1000baseT_Half)
1687 giga_ctrl |= ADVERTISE_1000HALF;
1688 if (adv & ADVERTISED_1000baseT_Full)
1689 giga_ctrl |= ADVERTISE_1000FULL;
1690 } else if (adv & (ADVERTISED_1000baseT_Half |
1691 ADVERTISED_1000baseT_Full)) {
Joe Perchesbf82c182010-02-09 11:49:50 +00001692 netif_info(tp, link, dev,
1693 "PHY does not support 1000Mbps\n");
Oliver Neukum54405cd2011-01-06 21:55:13 +01001694 goto out;
Francois Romieubcf0bf92006-07-26 23:14:13 +02001695 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696
françois romieu3577aa12009-05-19 10:46:48 +00001697 bmcr = BMCR_ANENABLE | BMCR_ANRESTART;
Francois Romieu623a1592006-05-14 12:42:14 +02001698
françois romieu4da19632011-01-03 15:07:55 +00001699 rtl_writephy(tp, MII_ADVERTISE, auto_nego);
1700 rtl_writephy(tp, MII_CTRL1000, giga_ctrl);
françois romieu3577aa12009-05-19 10:46:48 +00001701 } else {
1702 giga_ctrl = 0;
1703
1704 if (speed == SPEED_10)
1705 bmcr = 0;
1706 else if (speed == SPEED_100)
1707 bmcr = BMCR_SPEED100;
1708 else
Oliver Neukum54405cd2011-01-06 21:55:13 +01001709 goto out;
françois romieu3577aa12009-05-19 10:46:48 +00001710
1711 if (duplex == DUPLEX_FULL)
1712 bmcr |= BMCR_FULLDPLX;
Roger So2584fbc2007-07-31 23:52:42 +02001713 }
1714
françois romieu4da19632011-01-03 15:07:55 +00001715 rtl_writephy(tp, MII_BMCR, bmcr);
françois romieu3577aa12009-05-19 10:46:48 +00001716
Francois Romieucecb5fd2011-04-01 10:21:07 +02001717 if (tp->mac_version == RTL_GIGA_MAC_VER_02 ||
1718 tp->mac_version == RTL_GIGA_MAC_VER_03) {
françois romieu3577aa12009-05-19 10:46:48 +00001719 if ((speed == SPEED_100) && (autoneg != AUTONEG_ENABLE)) {
françois romieu4da19632011-01-03 15:07:55 +00001720 rtl_writephy(tp, 0x17, 0x2138);
1721 rtl_writephy(tp, 0x0e, 0x0260);
françois romieu3577aa12009-05-19 10:46:48 +00001722 } else {
françois romieu4da19632011-01-03 15:07:55 +00001723 rtl_writephy(tp, 0x17, 0x2108);
1724 rtl_writephy(tp, 0x0e, 0x0000);
françois romieu3577aa12009-05-19 10:46:48 +00001725 }
1726 }
1727
Oliver Neukum54405cd2011-01-06 21:55:13 +01001728 rc = 0;
1729out:
1730 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731}
1732
1733static int rtl8169_set_speed(struct net_device *dev,
Oliver Neukum54405cd2011-01-06 21:55:13 +01001734 u8 autoneg, u16 speed, u8 duplex, u32 advertising)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735{
1736 struct rtl8169_private *tp = netdev_priv(dev);
1737 int ret;
1738
Oliver Neukum54405cd2011-01-06 21:55:13 +01001739 ret = tp->set_speed(dev, autoneg, speed, duplex, advertising);
Francois Romieu4876cc12011-03-11 21:07:11 +01001740 if (ret < 0)
1741 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001742
Francois Romieu4876cc12011-03-11 21:07:11 +01001743 if (netif_running(dev) && (autoneg == AUTONEG_ENABLE) &&
1744 (advertising & ADVERTISED_1000baseT_Full)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001745 mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT);
Francois Romieu4876cc12011-03-11 21:07:11 +01001746 }
1747out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001748 return ret;
1749}
1750
1751static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
1752{
1753 struct rtl8169_private *tp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754 int ret;
1755
Francois Romieu4876cc12011-03-11 21:07:11 +01001756 del_timer_sync(&tp->timer);
1757
Francois Romieuda78dbf2012-01-26 14:18:23 +01001758 rtl_lock_work(tp);
Francois Romieucecb5fd2011-04-01 10:21:07 +02001759 ret = rtl8169_set_speed(dev, cmd->autoneg, ethtool_cmd_speed(cmd),
David Decotigny25db0332011-04-27 18:32:39 +00001760 cmd->duplex, cmd->advertising);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001761 rtl_unlock_work(tp);
Francois Romieu5b0384f2006-08-16 16:00:01 +02001762
Linus Torvalds1da177e2005-04-16 15:20:36 -07001763 return ret;
1764}
1765
Michał Mirosławc8f44af2011-11-15 15:29:55 +00001766static netdev_features_t rtl8169_fix_features(struct net_device *dev,
1767 netdev_features_t features)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001768{
Francois Romieud58d46b2011-05-03 16:38:29 +02001769 struct rtl8169_private *tp = netdev_priv(dev);
1770
Francois Romieu2b7b4312011-04-18 22:53:24 -07001771 if (dev->mtu > TD_MSS_MAX)
Michał Mirosław350fb322011-04-08 06:35:56 +00001772 features &= ~NETIF_F_ALL_TSO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001773
Francois Romieud58d46b2011-05-03 16:38:29 +02001774 if (dev->mtu > JUMBO_1K &&
1775 !rtl_chip_infos[tp->mac_version].jumbo_tx_csum)
1776 features &= ~NETIF_F_IP_CSUM;
1777
Michał Mirosław350fb322011-04-08 06:35:56 +00001778 return features;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001779}
1780
Francois Romieuda78dbf2012-01-26 14:18:23 +01001781static void __rtl8169_set_features(struct net_device *dev,
1782 netdev_features_t features)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783{
1784 struct rtl8169_private *tp = netdev_priv(dev);
Ben Greear6bbe0212012-02-10 15:04:33 +00001785 netdev_features_t changed = features ^ dev->features;
Francois Romieuda78dbf2012-01-26 14:18:23 +01001786 void __iomem *ioaddr = tp->mmio_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001787
Patrick McHardyf6469682013-04-19 02:04:27 +00001788 if (!(changed & (NETIF_F_RXALL | NETIF_F_RXCSUM |
1789 NETIF_F_HW_VLAN_CTAG_RX)))
Ben Greear6bbe0212012-02-10 15:04:33 +00001790 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001791
Patrick McHardyf6469682013-04-19 02:04:27 +00001792 if (changed & (NETIF_F_RXCSUM | NETIF_F_HW_VLAN_CTAG_RX)) {
Ben Greear6bbe0212012-02-10 15:04:33 +00001793 if (features & NETIF_F_RXCSUM)
1794 tp->cp_cmd |= RxChkSum;
1795 else
1796 tp->cp_cmd &= ~RxChkSum;
Michał Mirosław350fb322011-04-08 06:35:56 +00001797
Patrick McHardyf6469682013-04-19 02:04:27 +00001798 if (dev->features & NETIF_F_HW_VLAN_CTAG_RX)
Ben Greear6bbe0212012-02-10 15:04:33 +00001799 tp->cp_cmd |= RxVlan;
1800 else
1801 tp->cp_cmd &= ~RxVlan;
1802
1803 RTL_W16(CPlusCmd, tp->cp_cmd);
1804 RTL_R16(CPlusCmd);
1805 }
1806 if (changed & NETIF_F_RXALL) {
1807 int tmp = (RTL_R32(RxConfig) & ~(AcceptErr | AcceptRunt));
1808 if (features & NETIF_F_RXALL)
1809 tmp |= (AcceptErr | AcceptRunt);
1810 RTL_W32(RxConfig, tmp);
1811 }
Francois Romieuda78dbf2012-01-26 14:18:23 +01001812}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001813
Francois Romieuda78dbf2012-01-26 14:18:23 +01001814static int rtl8169_set_features(struct net_device *dev,
1815 netdev_features_t features)
1816{
1817 struct rtl8169_private *tp = netdev_priv(dev);
1818
1819 rtl_lock_work(tp);
1820 __rtl8169_set_features(dev, features);
1821 rtl_unlock_work(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001822
1823 return 0;
1824}
1825
Francois Romieuda78dbf2012-01-26 14:18:23 +01001826
Kirill Smelkov810f4892012-11-10 21:11:02 +04001827static inline u32 rtl8169_tx_vlan_tag(struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828{
Jesse Grosseab6d182010-10-20 13:56:03 +00001829 return (vlan_tx_tag_present(skb)) ?
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830 TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00;
1831}
1832
Francois Romieu7a8fc772011-03-01 17:18:33 +01001833static void rtl8169_rx_vlan_tag(struct RxDesc *desc, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001834{
1835 u32 opts2 = le32_to_cpu(desc->opts2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836
Francois Romieu7a8fc772011-03-01 17:18:33 +01001837 if (opts2 & RxVlanTag)
Patrick McHardy86a9bad2013-04-19 02:04:30 +00001838 __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), swab16(opts2 & 0xffff));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001839}
1840
Francois Romieuccdffb92008-07-26 14:26:06 +02001841static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842{
1843 struct rtl8169_private *tp = netdev_priv(dev);
1844 void __iomem *ioaddr = tp->mmio_addr;
1845 u32 status;
1846
1847 cmd->supported =
1848 SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE;
1849 cmd->port = PORT_FIBRE;
1850 cmd->transceiver = XCVR_INTERNAL;
1851
1852 status = RTL_R32(TBICSR);
1853 cmd->advertising = (status & TBINwEnable) ? ADVERTISED_Autoneg : 0;
1854 cmd->autoneg = !!(status & TBINwEnable);
1855
David Decotigny70739492011-04-27 18:32:40 +00001856 ethtool_cmd_speed_set(cmd, SPEED_1000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857 cmd->duplex = DUPLEX_FULL; /* Always set */
Francois Romieuccdffb92008-07-26 14:26:06 +02001858
1859 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001860}
1861
Francois Romieuccdffb92008-07-26 14:26:06 +02001862static int rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863{
1864 struct rtl8169_private *tp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865
Francois Romieuccdffb92008-07-26 14:26:06 +02001866 return mii_ethtool_gset(&tp->mii, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001867}
1868
1869static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
1870{
1871 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieuccdffb92008-07-26 14:26:06 +02001872 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001873
Francois Romieuda78dbf2012-01-26 14:18:23 +01001874 rtl_lock_work(tp);
Francois Romieuccdffb92008-07-26 14:26:06 +02001875 rc = tp->get_settings(dev, cmd);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001876 rtl_unlock_work(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877
Francois Romieuccdffb92008-07-26 14:26:06 +02001878 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001879}
1880
1881static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs,
1882 void *p)
1883{
Francois Romieu5b0384f2006-08-16 16:00:01 +02001884 struct rtl8169_private *tp = netdev_priv(dev);
Peter Wu15edae92013-08-21 23:17:11 +02001885 u32 __iomem *data = tp->mmio_addr;
1886 u32 *dw = p;
1887 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001888
Francois Romieuda78dbf2012-01-26 14:18:23 +01001889 rtl_lock_work(tp);
Peter Wu15edae92013-08-21 23:17:11 +02001890 for (i = 0; i < R8169_REGS_SIZE; i += 4)
1891 memcpy_fromio(dw++, data++, 4);
Francois Romieuda78dbf2012-01-26 14:18:23 +01001892 rtl_unlock_work(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893}
1894
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +02001895static u32 rtl8169_get_msglevel(struct net_device *dev)
1896{
1897 struct rtl8169_private *tp = netdev_priv(dev);
1898
1899 return tp->msg_enable;
1900}
1901
1902static void rtl8169_set_msglevel(struct net_device *dev, u32 value)
1903{
1904 struct rtl8169_private *tp = netdev_priv(dev);
1905
1906 tp->msg_enable = value;
1907}
1908
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001909static const char rtl8169_gstrings[][ETH_GSTRING_LEN] = {
1910 "tx_packets",
1911 "rx_packets",
1912 "tx_errors",
1913 "rx_errors",
1914 "rx_missed",
1915 "align_errors",
1916 "tx_single_collisions",
1917 "tx_multi_collisions",
1918 "unicast",
1919 "broadcast",
1920 "multicast",
1921 "tx_aborted",
1922 "tx_underrun",
1923};
1924
Jeff Garzikb9f2c042007-10-03 18:07:32 -07001925static int rtl8169_get_sset_count(struct net_device *dev, int sset)
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001926{
Jeff Garzikb9f2c042007-10-03 18:07:32 -07001927 switch (sset) {
1928 case ETH_SS_STATS:
1929 return ARRAY_SIZE(rtl8169_gstrings);
1930 default:
1931 return -EOPNOTSUPP;
1932 }
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001933}
1934
Francois Romieuffc46952012-07-06 14:19:23 +02001935DECLARE_RTL_COND(rtl_counters_cond)
1936{
1937 void __iomem *ioaddr = tp->mmio_addr;
1938
1939 return RTL_R32(CounterAddrLow) & CounterDump;
1940}
1941
Ivan Vecera355423d2009-02-06 21:49:57 -08001942static void rtl8169_update_counters(struct net_device *dev)
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001943{
1944 struct rtl8169_private *tp = netdev_priv(dev);
1945 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieucecb5fd2011-04-01 10:21:07 +02001946 struct device *d = &tp->pci_dev->dev;
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001947 struct rtl8169_counters *counters;
1948 dma_addr_t paddr;
1949 u32 cmd;
1950
Ivan Vecera355423d2009-02-06 21:49:57 -08001951 /*
1952 * Some chips are unable to dump tally counters when the receiver
1953 * is disabled.
1954 */
1955 if ((RTL_R8(ChipCmd) & CmdRxEnb) == 0)
1956 return;
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001957
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00001958 counters = dma_alloc_coherent(d, sizeof(*counters), &paddr, GFP_KERNEL);
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001959 if (!counters)
1960 return;
1961
1962 RTL_W32(CounterAddrHigh, (u64)paddr >> 32);
Yang Hongyang284901a2009-04-06 19:01:15 -07001963 cmd = (u64)paddr & DMA_BIT_MASK(32);
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001964 RTL_W32(CounterAddrLow, cmd);
1965 RTL_W32(CounterAddrLow, cmd | CounterDump);
1966
Francois Romieuffc46952012-07-06 14:19:23 +02001967 if (rtl_udelay_loop_wait_low(tp, &rtl_counters_cond, 10, 1000))
1968 memcpy(&tp->counters, counters, sizeof(*counters));
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001969
1970 RTL_W32(CounterAddrLow, 0);
1971 RTL_W32(CounterAddrHigh, 0);
1972
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00001973 dma_free_coherent(d, sizeof(*counters), counters, paddr);
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02001974}
1975
Ivan Vecera355423d2009-02-06 21:49:57 -08001976static void rtl8169_get_ethtool_stats(struct net_device *dev,
1977 struct ethtool_stats *stats, u64 *data)
1978{
1979 struct rtl8169_private *tp = netdev_priv(dev);
1980
1981 ASSERT_RTNL();
1982
1983 rtl8169_update_counters(dev);
1984
1985 data[0] = le64_to_cpu(tp->counters.tx_packets);
1986 data[1] = le64_to_cpu(tp->counters.rx_packets);
1987 data[2] = le64_to_cpu(tp->counters.tx_errors);
1988 data[3] = le32_to_cpu(tp->counters.rx_errors);
1989 data[4] = le16_to_cpu(tp->counters.rx_missed);
1990 data[5] = le16_to_cpu(tp->counters.align_errors);
1991 data[6] = le32_to_cpu(tp->counters.tx_one_collision);
1992 data[7] = le32_to_cpu(tp->counters.tx_multi_collision);
1993 data[8] = le64_to_cpu(tp->counters.rx_unicast);
1994 data[9] = le64_to_cpu(tp->counters.rx_broadcast);
1995 data[10] = le32_to_cpu(tp->counters.rx_multicast);
1996 data[11] = le16_to_cpu(tp->counters.tx_aborted);
1997 data[12] = le16_to_cpu(tp->counters.tx_underun);
1998}
1999
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02002000static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data)
2001{
2002 switch(stringset) {
2003 case ETH_SS_STATS:
2004 memcpy(data, *rtl8169_gstrings, sizeof(rtl8169_gstrings));
2005 break;
2006 }
2007}
2008
Jeff Garzik7282d492006-09-13 14:30:00 -04002009static const struct ethtool_ops rtl8169_ethtool_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002010 .get_drvinfo = rtl8169_get_drvinfo,
2011 .get_regs_len = rtl8169_get_regs_len,
2012 .get_link = ethtool_op_get_link,
2013 .get_settings = rtl8169_get_settings,
2014 .set_settings = rtl8169_set_settings,
Stephen Hemmingerb57b7e52005-05-27 21:11:52 +02002015 .get_msglevel = rtl8169_get_msglevel,
2016 .set_msglevel = rtl8169_set_msglevel,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002017 .get_regs = rtl8169_get_regs,
Francois Romieu61a4dcc2006-02-23 00:55:25 +01002018 .get_wol = rtl8169_get_wol,
2019 .set_wol = rtl8169_set_wol,
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02002020 .get_strings = rtl8169_get_strings,
Jeff Garzikb9f2c042007-10-03 18:07:32 -07002021 .get_sset_count = rtl8169_get_sset_count,
Stephen Hemmingerd4a3a0f2005-05-27 21:11:56 +02002022 .get_ethtool_stats = rtl8169_get_ethtool_stats,
Richard Cochrane1593bb2012-04-03 22:59:35 +00002023 .get_ts_info = ethtool_op_get_ts_info,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002024};
2025
Francois Romieu07d3f512007-02-21 22:40:46 +01002026static void rtl8169_get_mac_version(struct rtl8169_private *tp,
Francois Romieu5d320a22011-05-08 17:47:36 +02002027 struct net_device *dev, u8 default_version)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002028{
Francois Romieu5d320a22011-05-08 17:47:36 +02002029 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu0e485152007-02-20 00:00:26 +01002030 /*
2031 * The driver currently handles the 8168Bf and the 8168Be identically
2032 * but they can be identified more specifically through the test below
2033 * if needed:
2034 *
2035 * (RTL_R32(TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be
Francois Romieu01272152007-02-20 22:58:51 +01002036 *
2037 * Same thing for the 8101Eb and the 8101Ec:
2038 *
2039 * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec
Francois Romieu0e485152007-02-20 00:00:26 +01002040 */
Francois Romieu37441002011-06-17 22:58:54 +02002041 static const struct rtl_mac_info {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002042 u32 mask;
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002043 u32 val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002044 int mac_version;
2045 } mac_info[] = {
Hayes Wangc5583862012-07-02 17:23:22 +08002046 /* 8168G family. */
hayeswang45dd95c2013-07-08 17:09:01 +08002047 { 0x7cf00000, 0x5c800000, RTL_GIGA_MAC_VER_44 },
hayeswang57538c42013-04-01 22:23:40 +00002048 { 0x7cf00000, 0x50900000, RTL_GIGA_MAC_VER_42 },
Hayes Wangc5583862012-07-02 17:23:22 +08002049 { 0x7cf00000, 0x4c100000, RTL_GIGA_MAC_VER_41 },
2050 { 0x7cf00000, 0x4c000000, RTL_GIGA_MAC_VER_40 },
2051
Hayes Wangc2218922011-09-06 16:55:18 +08002052 /* 8168F family. */
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08002053 { 0x7c800000, 0x48800000, RTL_GIGA_MAC_VER_38 },
Hayes Wangc2218922011-09-06 16:55:18 +08002054 { 0x7cf00000, 0x48100000, RTL_GIGA_MAC_VER_36 },
2055 { 0x7cf00000, 0x48000000, RTL_GIGA_MAC_VER_35 },
2056
hayeswang01dc7fe2011-03-21 01:50:28 +00002057 /* 8168E family. */
Hayes Wang70090422011-07-06 15:58:06 +08002058 { 0x7c800000, 0x2c800000, RTL_GIGA_MAC_VER_34 },
hayeswang01dc7fe2011-03-21 01:50:28 +00002059 { 0x7cf00000, 0x2c200000, RTL_GIGA_MAC_VER_33 },
2060 { 0x7cf00000, 0x2c100000, RTL_GIGA_MAC_VER_32 },
2061 { 0x7c800000, 0x2c000000, RTL_GIGA_MAC_VER_33 },
2062
Francois Romieu5b538df2008-07-20 16:22:45 +02002063 /* 8168D family. */
françois romieudaf9df62009-10-07 12:44:20 +00002064 { 0x7cf00000, 0x28300000, RTL_GIGA_MAC_VER_26 },
2065 { 0x7cf00000, 0x28100000, RTL_GIGA_MAC_VER_25 },
françois romieudaf9df62009-10-07 12:44:20 +00002066 { 0x7c800000, 0x28000000, RTL_GIGA_MAC_VER_26 },
Francois Romieu5b538df2008-07-20 16:22:45 +02002067
françois romieue6de30d2011-01-03 15:08:37 +00002068 /* 8168DP family. */
2069 { 0x7cf00000, 0x28800000, RTL_GIGA_MAC_VER_27 },
2070 { 0x7cf00000, 0x28a00000, RTL_GIGA_MAC_VER_28 },
hayeswang4804b3b2011-03-21 01:50:29 +00002071 { 0x7cf00000, 0x28b00000, RTL_GIGA_MAC_VER_31 },
françois romieue6de30d2011-01-03 15:08:37 +00002072
Francois Romieuef808d52008-06-29 13:10:54 +02002073 /* 8168C family. */
Francois Romieu17c99292010-07-11 17:10:09 -07002074 { 0x7cf00000, 0x3cb00000, RTL_GIGA_MAC_VER_24 },
Francois Romieuef3386f2008-06-29 12:24:30 +02002075 { 0x7cf00000, 0x3c900000, RTL_GIGA_MAC_VER_23 },
Francois Romieuef808d52008-06-29 13:10:54 +02002076 { 0x7cf00000, 0x3c800000, RTL_GIGA_MAC_VER_18 },
Francois Romieu7f3e3d32008-07-20 18:53:20 +02002077 { 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_24 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002078 { 0x7cf00000, 0x3c000000, RTL_GIGA_MAC_VER_19 },
2079 { 0x7cf00000, 0x3c200000, RTL_GIGA_MAC_VER_20 },
Francois Romieu197ff762008-06-28 13:16:02 +02002080 { 0x7cf00000, 0x3c300000, RTL_GIGA_MAC_VER_21 },
Francois Romieu6fb07052008-06-29 11:54:28 +02002081 { 0x7cf00000, 0x3c400000, RTL_GIGA_MAC_VER_22 },
Francois Romieuef808d52008-06-29 13:10:54 +02002082 { 0x7c800000, 0x3c000000, RTL_GIGA_MAC_VER_22 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002083
2084 /* 8168B family. */
2085 { 0x7cf00000, 0x38000000, RTL_GIGA_MAC_VER_12 },
2086 { 0x7cf00000, 0x38500000, RTL_GIGA_MAC_VER_17 },
2087 { 0x7c800000, 0x38000000, RTL_GIGA_MAC_VER_17 },
2088 { 0x7c800000, 0x30000000, RTL_GIGA_MAC_VER_11 },
2089
2090 /* 8101 family. */
Hayes Wang5598bfe2012-07-02 17:23:21 +08002091 { 0x7cf00000, 0x44900000, RTL_GIGA_MAC_VER_39 },
2092 { 0x7c800000, 0x44800000, RTL_GIGA_MAC_VER_39 },
Hayes Wang7e18dca2012-03-30 14:33:02 +08002093 { 0x7c800000, 0x44000000, RTL_GIGA_MAC_VER_37 },
hayeswang36a0e6c2011-03-21 01:50:30 +00002094 { 0x7cf00000, 0x40b00000, RTL_GIGA_MAC_VER_30 },
Hayes Wang5a5e4442011-02-22 17:26:21 +08002095 { 0x7cf00000, 0x40a00000, RTL_GIGA_MAC_VER_30 },
2096 { 0x7cf00000, 0x40900000, RTL_GIGA_MAC_VER_29 },
2097 { 0x7c800000, 0x40800000, RTL_GIGA_MAC_VER_30 },
Francois Romieu2857ffb2008-08-02 21:08:49 +02002098 { 0x7cf00000, 0x34a00000, RTL_GIGA_MAC_VER_09 },
2099 { 0x7cf00000, 0x24a00000, RTL_GIGA_MAC_VER_09 },
2100 { 0x7cf00000, 0x34900000, RTL_GIGA_MAC_VER_08 },
2101 { 0x7cf00000, 0x24900000, RTL_GIGA_MAC_VER_08 },
2102 { 0x7cf00000, 0x34800000, RTL_GIGA_MAC_VER_07 },
2103 { 0x7cf00000, 0x24800000, RTL_GIGA_MAC_VER_07 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002104 { 0x7cf00000, 0x34000000, RTL_GIGA_MAC_VER_13 },
Francois Romieu2857ffb2008-08-02 21:08:49 +02002105 { 0x7cf00000, 0x34300000, RTL_GIGA_MAC_VER_10 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002106 { 0x7cf00000, 0x34200000, RTL_GIGA_MAC_VER_16 },
Francois Romieu2857ffb2008-08-02 21:08:49 +02002107 { 0x7c800000, 0x34800000, RTL_GIGA_MAC_VER_09 },
2108 { 0x7c800000, 0x24800000, RTL_GIGA_MAC_VER_09 },
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002109 { 0x7c800000, 0x34000000, RTL_GIGA_MAC_VER_16 },
2110 /* FIXME: where did these entries come from ? -- FR */
2111 { 0xfc800000, 0x38800000, RTL_GIGA_MAC_VER_15 },
2112 { 0xfc800000, 0x30800000, RTL_GIGA_MAC_VER_14 },
2113
2114 /* 8110 family. */
2115 { 0xfc800000, 0x98000000, RTL_GIGA_MAC_VER_06 },
2116 { 0xfc800000, 0x18000000, RTL_GIGA_MAC_VER_05 },
2117 { 0xfc800000, 0x10000000, RTL_GIGA_MAC_VER_04 },
2118 { 0xfc800000, 0x04000000, RTL_GIGA_MAC_VER_03 },
2119 { 0xfc800000, 0x00800000, RTL_GIGA_MAC_VER_02 },
2120 { 0xfc800000, 0x00000000, RTL_GIGA_MAC_VER_01 },
2121
Jean Delvaref21b75e2009-05-26 20:54:48 -07002122 /* Catch-all */
2123 { 0x00000000, 0x00000000, RTL_GIGA_MAC_NONE }
Francois Romieu37441002011-06-17 22:58:54 +02002124 };
2125 const struct rtl_mac_info *p = mac_info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002126 u32 reg;
2127
Francois Romieue3cf0cc2007-08-17 14:55:46 +02002128 reg = RTL_R32(TxConfig);
2129 while ((reg & p->mask) != p->val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002130 p++;
2131 tp->mac_version = p->mac_version;
Francois Romieu5d320a22011-05-08 17:47:36 +02002132
2133 if (tp->mac_version == RTL_GIGA_MAC_NONE) {
2134 netif_notice(tp, probe, dev,
2135 "unknown MAC, using family default\n");
2136 tp->mac_version = default_version;
hayeswang58152cd2013-04-01 22:23:42 +00002137 } else if (tp->mac_version == RTL_GIGA_MAC_VER_42) {
2138 tp->mac_version = tp->mii.supports_gmii ?
2139 RTL_GIGA_MAC_VER_42 :
2140 RTL_GIGA_MAC_VER_43;
Francois Romieu5d320a22011-05-08 17:47:36 +02002141 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002142}
2143
2144static void rtl8169_print_mac_version(struct rtl8169_private *tp)
2145{
Francois Romieubcf0bf92006-07-26 23:14:13 +02002146 dprintk("mac_version = 0x%02x\n", tp->mac_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002147}
2148
Francois Romieu867763c2007-08-17 18:21:58 +02002149struct phy_reg {
2150 u16 reg;
2151 u16 val;
2152};
2153
françois romieu4da19632011-01-03 15:07:55 +00002154static void rtl_writephy_batch(struct rtl8169_private *tp,
2155 const struct phy_reg *regs, int len)
Francois Romieu867763c2007-08-17 18:21:58 +02002156{
2157 while (len-- > 0) {
françois romieu4da19632011-01-03 15:07:55 +00002158 rtl_writephy(tp, regs->reg, regs->val);
Francois Romieu867763c2007-08-17 18:21:58 +02002159 regs++;
2160 }
2161}
2162
françois romieubca03d52011-01-03 15:07:31 +00002163#define PHY_READ 0x00000000
2164#define PHY_DATA_OR 0x10000000
2165#define PHY_DATA_AND 0x20000000
2166#define PHY_BJMPN 0x30000000
hayeswangeee37862013-04-01 22:23:38 +00002167#define PHY_MDIO_CHG 0x40000000
françois romieubca03d52011-01-03 15:07:31 +00002168#define PHY_CLEAR_READCOUNT 0x70000000
2169#define PHY_WRITE 0x80000000
2170#define PHY_READCOUNT_EQ_SKIP 0x90000000
2171#define PHY_COMP_EQ_SKIPN 0xa0000000
2172#define PHY_COMP_NEQ_SKIPN 0xb0000000
2173#define PHY_WRITE_PREVIOUS 0xc0000000
2174#define PHY_SKIPN 0xd0000000
2175#define PHY_DELAY_MS 0xe0000000
françois romieubca03d52011-01-03 15:07:31 +00002176
Hayes Wang960aee62011-06-18 11:37:48 +02002177struct fw_info {
2178 u32 magic;
2179 char version[RTL_VER_SIZE];
2180 __le32 fw_start;
2181 __le32 fw_len;
2182 u8 chksum;
2183} __packed;
2184
Francois Romieu1c361ef2011-06-17 17:16:24 +02002185#define FW_OPCODE_SIZE sizeof(typeof(*((struct rtl_fw_phy_action *)0)->code))
2186
2187static bool rtl_fw_format_ok(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
françois romieubca03d52011-01-03 15:07:31 +00002188{
Francois Romieub6ffd972011-06-17 17:00:05 +02002189 const struct firmware *fw = rtl_fw->fw;
Hayes Wang960aee62011-06-18 11:37:48 +02002190 struct fw_info *fw_info = (struct fw_info *)fw->data;
Francois Romieu1c361ef2011-06-17 17:16:24 +02002191 struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
2192 char *version = rtl_fw->version;
2193 bool rc = false;
françois romieubca03d52011-01-03 15:07:31 +00002194
Francois Romieu1c361ef2011-06-17 17:16:24 +02002195 if (fw->size < FW_OPCODE_SIZE)
2196 goto out;
Hayes Wang960aee62011-06-18 11:37:48 +02002197
2198 if (!fw_info->magic) {
2199 size_t i, size, start;
2200 u8 checksum = 0;
2201
2202 if (fw->size < sizeof(*fw_info))
2203 goto out;
2204
2205 for (i = 0; i < fw->size; i++)
2206 checksum += fw->data[i];
2207 if (checksum != 0)
2208 goto out;
2209
2210 start = le32_to_cpu(fw_info->fw_start);
2211 if (start > fw->size)
2212 goto out;
2213
2214 size = le32_to_cpu(fw_info->fw_len);
2215 if (size > (fw->size - start) / FW_OPCODE_SIZE)
2216 goto out;
2217
2218 memcpy(version, fw_info->version, RTL_VER_SIZE);
2219
2220 pa->code = (__le32 *)(fw->data + start);
2221 pa->size = size;
2222 } else {
Francois Romieu1c361ef2011-06-17 17:16:24 +02002223 if (fw->size % FW_OPCODE_SIZE)
2224 goto out;
2225
2226 strlcpy(version, rtl_lookup_firmware_name(tp), RTL_VER_SIZE);
2227
2228 pa->code = (__le32 *)fw->data;
2229 pa->size = fw->size / FW_OPCODE_SIZE;
2230 }
2231 version[RTL_VER_SIZE - 1] = 0;
2232
2233 rc = true;
2234out:
2235 return rc;
2236}
2237
Francois Romieufd112f22011-06-18 00:10:29 +02002238static bool rtl_fw_data_ok(struct rtl8169_private *tp, struct net_device *dev,
2239 struct rtl_fw_phy_action *pa)
Francois Romieu1c361ef2011-06-17 17:16:24 +02002240{
Francois Romieufd112f22011-06-18 00:10:29 +02002241 bool rc = false;
Francois Romieu1c361ef2011-06-17 17:16:24 +02002242 size_t index;
2243
Francois Romieu1c361ef2011-06-17 17:16:24 +02002244 for (index = 0; index < pa->size; index++) {
2245 u32 action = le32_to_cpu(pa->code[index]);
hayeswang42b82dc2011-01-10 02:07:25 +00002246 u32 regno = (action & 0x0fff0000) >> 16;
françois romieubca03d52011-01-03 15:07:31 +00002247
hayeswang42b82dc2011-01-10 02:07:25 +00002248 switch(action & 0xf0000000) {
2249 case PHY_READ:
2250 case PHY_DATA_OR:
2251 case PHY_DATA_AND:
hayeswangeee37862013-04-01 22:23:38 +00002252 case PHY_MDIO_CHG:
hayeswang42b82dc2011-01-10 02:07:25 +00002253 case PHY_CLEAR_READCOUNT:
2254 case PHY_WRITE:
2255 case PHY_WRITE_PREVIOUS:
2256 case PHY_DELAY_MS:
françois romieubca03d52011-01-03 15:07:31 +00002257 break;
2258
hayeswang42b82dc2011-01-10 02:07:25 +00002259 case PHY_BJMPN:
2260 if (regno > index) {
Francois Romieufd112f22011-06-18 00:10:29 +02002261 netif_err(tp, ifup, tp->dev,
Francois Romieucecb5fd2011-04-01 10:21:07 +02002262 "Out of range of firmware\n");
Francois Romieufd112f22011-06-18 00:10:29 +02002263 goto out;
hayeswang42b82dc2011-01-10 02:07:25 +00002264 }
2265 break;
2266 case PHY_READCOUNT_EQ_SKIP:
Francois Romieu1c361ef2011-06-17 17:16:24 +02002267 if (index + 2 >= pa->size) {
Francois Romieufd112f22011-06-18 00:10:29 +02002268 netif_err(tp, ifup, tp->dev,
Francois Romieucecb5fd2011-04-01 10:21:07 +02002269 "Out of range of firmware\n");
Francois Romieufd112f22011-06-18 00:10:29 +02002270 goto out;
hayeswang42b82dc2011-01-10 02:07:25 +00002271 }
2272 break;
2273 case PHY_COMP_EQ_SKIPN:
2274 case PHY_COMP_NEQ_SKIPN:
2275 case PHY_SKIPN:
Francois Romieu1c361ef2011-06-17 17:16:24 +02002276 if (index + 1 + regno >= pa->size) {
Francois Romieufd112f22011-06-18 00:10:29 +02002277 netif_err(tp, ifup, tp->dev,
Francois Romieucecb5fd2011-04-01 10:21:07 +02002278 "Out of range of firmware\n");
Francois Romieufd112f22011-06-18 00:10:29 +02002279 goto out;
hayeswang42b82dc2011-01-10 02:07:25 +00002280 }
2281 break;
2282
hayeswang42b82dc2011-01-10 02:07:25 +00002283 default:
Francois Romieufd112f22011-06-18 00:10:29 +02002284 netif_err(tp, ifup, tp->dev,
hayeswang42b82dc2011-01-10 02:07:25 +00002285 "Invalid action 0x%08x\n", action);
Francois Romieufd112f22011-06-18 00:10:29 +02002286 goto out;
françois romieubca03d52011-01-03 15:07:31 +00002287 }
2288 }
Francois Romieufd112f22011-06-18 00:10:29 +02002289 rc = true;
2290out:
2291 return rc;
2292}
françois romieubca03d52011-01-03 15:07:31 +00002293
Francois Romieufd112f22011-06-18 00:10:29 +02002294static int rtl_check_firmware(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
2295{
2296 struct net_device *dev = tp->dev;
2297 int rc = -EINVAL;
2298
2299 if (!rtl_fw_format_ok(tp, rtl_fw)) {
2300 netif_err(tp, ifup, dev, "invalid firwmare\n");
2301 goto out;
2302 }
2303
2304 if (rtl_fw_data_ok(tp, dev, &rtl_fw->phy_action))
2305 rc = 0;
2306out:
2307 return rc;
2308}
2309
2310static void rtl_phy_write_fw(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
2311{
2312 struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
hayeswangeee37862013-04-01 22:23:38 +00002313 struct mdio_ops org, *ops = &tp->mdio_ops;
Francois Romieufd112f22011-06-18 00:10:29 +02002314 u32 predata, count;
2315 size_t index;
2316
2317 predata = count = 0;
hayeswangeee37862013-04-01 22:23:38 +00002318 org.write = ops->write;
2319 org.read = ops->read;
hayeswang42b82dc2011-01-10 02:07:25 +00002320
Francois Romieu1c361ef2011-06-17 17:16:24 +02002321 for (index = 0; index < pa->size; ) {
2322 u32 action = le32_to_cpu(pa->code[index]);
françois romieubca03d52011-01-03 15:07:31 +00002323 u32 data = action & 0x0000ffff;
hayeswang42b82dc2011-01-10 02:07:25 +00002324 u32 regno = (action & 0x0fff0000) >> 16;
2325
2326 if (!action)
2327 break;
françois romieubca03d52011-01-03 15:07:31 +00002328
2329 switch(action & 0xf0000000) {
hayeswang42b82dc2011-01-10 02:07:25 +00002330 case PHY_READ:
2331 predata = rtl_readphy(tp, regno);
2332 count++;
2333 index++;
françois romieubca03d52011-01-03 15:07:31 +00002334 break;
hayeswang42b82dc2011-01-10 02:07:25 +00002335 case PHY_DATA_OR:
2336 predata |= data;
2337 index++;
2338 break;
2339 case PHY_DATA_AND:
2340 predata &= data;
2341 index++;
2342 break;
2343 case PHY_BJMPN:
2344 index -= regno;
2345 break;
hayeswangeee37862013-04-01 22:23:38 +00002346 case PHY_MDIO_CHG:
2347 if (data == 0) {
2348 ops->write = org.write;
2349 ops->read = org.read;
2350 } else if (data == 1) {
2351 ops->write = mac_mcu_write;
2352 ops->read = mac_mcu_read;
2353 }
2354
hayeswang42b82dc2011-01-10 02:07:25 +00002355 index++;
2356 break;
2357 case PHY_CLEAR_READCOUNT:
2358 count = 0;
2359 index++;
2360 break;
2361 case PHY_WRITE:
2362 rtl_writephy(tp, regno, data);
2363 index++;
2364 break;
2365 case PHY_READCOUNT_EQ_SKIP:
Francois Romieucecb5fd2011-04-01 10:21:07 +02002366 index += (count == data) ? 2 : 1;
hayeswang42b82dc2011-01-10 02:07:25 +00002367 break;
2368 case PHY_COMP_EQ_SKIPN:
2369 if (predata == data)
2370 index += regno;
2371 index++;
2372 break;
2373 case PHY_COMP_NEQ_SKIPN:
2374 if (predata != data)
2375 index += regno;
2376 index++;
2377 break;
2378 case PHY_WRITE_PREVIOUS:
2379 rtl_writephy(tp, regno, predata);
2380 index++;
2381 break;
2382 case PHY_SKIPN:
2383 index += regno + 1;
2384 break;
2385 case PHY_DELAY_MS:
2386 mdelay(data);
2387 index++;
2388 break;
2389
françois romieubca03d52011-01-03 15:07:31 +00002390 default:
2391 BUG();
2392 }
2393 }
hayeswangeee37862013-04-01 22:23:38 +00002394
2395 ops->write = org.write;
2396 ops->read = org.read;
françois romieubca03d52011-01-03 15:07:31 +00002397}
2398
françois romieuf1e02ed2011-01-13 13:07:53 +00002399static void rtl_release_firmware(struct rtl8169_private *tp)
2400{
Francois Romieub6ffd972011-06-17 17:00:05 +02002401 if (!IS_ERR_OR_NULL(tp->rtl_fw)) {
2402 release_firmware(tp->rtl_fw->fw);
2403 kfree(tp->rtl_fw);
2404 }
2405 tp->rtl_fw = RTL_FIRMWARE_UNKNOWN;
françois romieuf1e02ed2011-01-13 13:07:53 +00002406}
2407
François Romieu953a12c2011-04-24 17:38:48 +02002408static void rtl_apply_firmware(struct rtl8169_private *tp)
françois romieuf1e02ed2011-01-13 13:07:53 +00002409{
Francois Romieub6ffd972011-06-17 17:00:05 +02002410 struct rtl_fw *rtl_fw = tp->rtl_fw;
françois romieuf1e02ed2011-01-13 13:07:53 +00002411
2412 /* TODO: release firmware once rtl_phy_write_fw signals failures. */
Francois Romieueef63cc2013-02-08 23:43:20 +01002413 if (!IS_ERR_OR_NULL(rtl_fw))
Francois Romieub6ffd972011-06-17 17:00:05 +02002414 rtl_phy_write_fw(tp, rtl_fw);
François Romieu953a12c2011-04-24 17:38:48 +02002415}
2416
2417static void rtl_apply_firmware_cond(struct rtl8169_private *tp, u8 reg, u16 val)
2418{
2419 if (rtl_readphy(tp, reg) != val)
2420 netif_warn(tp, hw, tp->dev, "chipset not ready for firmware\n");
2421 else
2422 rtl_apply_firmware(tp);
françois romieuf1e02ed2011-01-13 13:07:53 +00002423}
2424
françois romieu4da19632011-01-03 15:07:55 +00002425static void rtl8169s_hw_phy_config(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002426{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002427 static const struct phy_reg phy_reg_init[] = {
françois romieu0b9b5712009-08-10 19:44:56 +00002428 { 0x1f, 0x0001 },
2429 { 0x06, 0x006e },
2430 { 0x08, 0x0708 },
2431 { 0x15, 0x4000 },
2432 { 0x18, 0x65c7 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07002433
françois romieu0b9b5712009-08-10 19:44:56 +00002434 { 0x1f, 0x0001 },
2435 { 0x03, 0x00a1 },
2436 { 0x02, 0x0008 },
2437 { 0x01, 0x0120 },
2438 { 0x00, 0x1000 },
2439 { 0x04, 0x0800 },
2440 { 0x04, 0x0000 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07002441
françois romieu0b9b5712009-08-10 19:44:56 +00002442 { 0x03, 0xff41 },
2443 { 0x02, 0xdf60 },
2444 { 0x01, 0x0140 },
2445 { 0x00, 0x0077 },
2446 { 0x04, 0x7800 },
2447 { 0x04, 0x7000 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07002448
françois romieu0b9b5712009-08-10 19:44:56 +00002449 { 0x03, 0x802f },
2450 { 0x02, 0x4f02 },
2451 { 0x01, 0x0409 },
2452 { 0x00, 0xf0f9 },
2453 { 0x04, 0x9800 },
2454 { 0x04, 0x9000 },
2455
2456 { 0x03, 0xdf01 },
2457 { 0x02, 0xdf20 },
2458 { 0x01, 0xff95 },
2459 { 0x00, 0xba00 },
2460 { 0x04, 0xa800 },
2461 { 0x04, 0xa000 },
2462
2463 { 0x03, 0xff41 },
2464 { 0x02, 0xdf20 },
2465 { 0x01, 0x0140 },
2466 { 0x00, 0x00bb },
2467 { 0x04, 0xb800 },
2468 { 0x04, 0xb000 },
2469
2470 { 0x03, 0xdf41 },
2471 { 0x02, 0xdc60 },
2472 { 0x01, 0x6340 },
2473 { 0x00, 0x007d },
2474 { 0x04, 0xd800 },
2475 { 0x04, 0xd000 },
2476
2477 { 0x03, 0xdf01 },
2478 { 0x02, 0xdf20 },
2479 { 0x01, 0x100a },
2480 { 0x00, 0xa0ff },
2481 { 0x04, 0xf800 },
2482 { 0x04, 0xf000 },
2483
2484 { 0x1f, 0x0000 },
2485 { 0x0b, 0x0000 },
2486 { 0x00, 0x9200 }
2487 };
2488
françois romieu4da19632011-01-03 15:07:55 +00002489 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002490}
2491
françois romieu4da19632011-01-03 15:07:55 +00002492static void rtl8169sb_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu5615d9f2007-08-17 17:50:46 +02002493{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002494 static const struct phy_reg phy_reg_init[] = {
Francois Romieua441d7b2007-08-17 18:26:35 +02002495 { 0x1f, 0x0002 },
2496 { 0x01, 0x90d0 },
2497 { 0x1f, 0x0000 }
2498 };
2499
françois romieu4da19632011-01-03 15:07:55 +00002500 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu5615d9f2007-08-17 17:50:46 +02002501}
2502
françois romieu4da19632011-01-03 15:07:55 +00002503static void rtl8169scd_hw_phy_config_quirk(struct rtl8169_private *tp)
françois romieu2e9558562009-08-10 19:44:19 +00002504{
2505 struct pci_dev *pdev = tp->pci_dev;
françois romieu2e9558562009-08-10 19:44:19 +00002506
Sergei Shtylyovccbae552011-07-22 05:37:24 +00002507 if ((pdev->subsystem_vendor != PCI_VENDOR_ID_GIGABYTE) ||
2508 (pdev->subsystem_device != 0xe000))
françois romieu2e9558562009-08-10 19:44:19 +00002509 return;
2510
françois romieu4da19632011-01-03 15:07:55 +00002511 rtl_writephy(tp, 0x1f, 0x0001);
2512 rtl_writephy(tp, 0x10, 0xf01b);
2513 rtl_writephy(tp, 0x1f, 0x0000);
françois romieu2e9558562009-08-10 19:44:19 +00002514}
2515
françois romieu4da19632011-01-03 15:07:55 +00002516static void rtl8169scd_hw_phy_config(struct rtl8169_private *tp)
françois romieu2e9558562009-08-10 19:44:19 +00002517{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002518 static const struct phy_reg phy_reg_init[] = {
françois romieu2e9558562009-08-10 19:44:19 +00002519 { 0x1f, 0x0001 },
2520 { 0x04, 0x0000 },
2521 { 0x03, 0x00a1 },
2522 { 0x02, 0x0008 },
2523 { 0x01, 0x0120 },
2524 { 0x00, 0x1000 },
2525 { 0x04, 0x0800 },
2526 { 0x04, 0x9000 },
2527 { 0x03, 0x802f },
2528 { 0x02, 0x4f02 },
2529 { 0x01, 0x0409 },
2530 { 0x00, 0xf099 },
2531 { 0x04, 0x9800 },
2532 { 0x04, 0xa000 },
2533 { 0x03, 0xdf01 },
2534 { 0x02, 0xdf20 },
2535 { 0x01, 0xff95 },
2536 { 0x00, 0xba00 },
2537 { 0x04, 0xa800 },
2538 { 0x04, 0xf000 },
2539 { 0x03, 0xdf01 },
2540 { 0x02, 0xdf20 },
2541 { 0x01, 0x101a },
2542 { 0x00, 0xa0ff },
2543 { 0x04, 0xf800 },
2544 { 0x04, 0x0000 },
2545 { 0x1f, 0x0000 },
2546
2547 { 0x1f, 0x0001 },
2548 { 0x10, 0xf41b },
2549 { 0x14, 0xfb54 },
2550 { 0x18, 0xf5c7 },
2551 { 0x1f, 0x0000 },
2552
2553 { 0x1f, 0x0001 },
2554 { 0x17, 0x0cc0 },
2555 { 0x1f, 0x0000 }
2556 };
2557
françois romieu4da19632011-01-03 15:07:55 +00002558 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieu2e9558562009-08-10 19:44:19 +00002559
françois romieu4da19632011-01-03 15:07:55 +00002560 rtl8169scd_hw_phy_config_quirk(tp);
françois romieu2e9558562009-08-10 19:44:19 +00002561}
2562
françois romieu4da19632011-01-03 15:07:55 +00002563static void rtl8169sce_hw_phy_config(struct rtl8169_private *tp)
françois romieu8c7006a2009-08-10 19:43:29 +00002564{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002565 static const struct phy_reg phy_reg_init[] = {
françois romieu8c7006a2009-08-10 19:43:29 +00002566 { 0x1f, 0x0001 },
2567 { 0x04, 0x0000 },
2568 { 0x03, 0x00a1 },
2569 { 0x02, 0x0008 },
2570 { 0x01, 0x0120 },
2571 { 0x00, 0x1000 },
2572 { 0x04, 0x0800 },
2573 { 0x04, 0x9000 },
2574 { 0x03, 0x802f },
2575 { 0x02, 0x4f02 },
2576 { 0x01, 0x0409 },
2577 { 0x00, 0xf099 },
2578 { 0x04, 0x9800 },
2579 { 0x04, 0xa000 },
2580 { 0x03, 0xdf01 },
2581 { 0x02, 0xdf20 },
2582 { 0x01, 0xff95 },
2583 { 0x00, 0xba00 },
2584 { 0x04, 0xa800 },
2585 { 0x04, 0xf000 },
2586 { 0x03, 0xdf01 },
2587 { 0x02, 0xdf20 },
2588 { 0x01, 0x101a },
2589 { 0x00, 0xa0ff },
2590 { 0x04, 0xf800 },
2591 { 0x04, 0x0000 },
2592 { 0x1f, 0x0000 },
2593
2594 { 0x1f, 0x0001 },
2595 { 0x0b, 0x8480 },
2596 { 0x1f, 0x0000 },
2597
2598 { 0x1f, 0x0001 },
2599 { 0x18, 0x67c7 },
2600 { 0x04, 0x2000 },
2601 { 0x03, 0x002f },
2602 { 0x02, 0x4360 },
2603 { 0x01, 0x0109 },
2604 { 0x00, 0x3022 },
2605 { 0x04, 0x2800 },
2606 { 0x1f, 0x0000 },
2607
2608 { 0x1f, 0x0001 },
2609 { 0x17, 0x0cc0 },
2610 { 0x1f, 0x0000 }
2611 };
2612
françois romieu4da19632011-01-03 15:07:55 +00002613 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieu8c7006a2009-08-10 19:43:29 +00002614}
2615
françois romieu4da19632011-01-03 15:07:55 +00002616static void rtl8168bb_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu236b8082008-05-30 16:11:48 +02002617{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002618 static const struct phy_reg phy_reg_init[] = {
Francois Romieu236b8082008-05-30 16:11:48 +02002619 { 0x10, 0xf41b },
2620 { 0x1f, 0x0000 }
2621 };
2622
françois romieu4da19632011-01-03 15:07:55 +00002623 rtl_writephy(tp, 0x1f, 0x0001);
2624 rtl_patchphy(tp, 0x16, 1 << 0);
Francois Romieu236b8082008-05-30 16:11:48 +02002625
françois romieu4da19632011-01-03 15:07:55 +00002626 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu236b8082008-05-30 16:11:48 +02002627}
2628
françois romieu4da19632011-01-03 15:07:55 +00002629static void rtl8168bef_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu236b8082008-05-30 16:11:48 +02002630{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002631 static const struct phy_reg phy_reg_init[] = {
Francois Romieu236b8082008-05-30 16:11:48 +02002632 { 0x1f, 0x0001 },
2633 { 0x10, 0xf41b },
2634 { 0x1f, 0x0000 }
2635 };
2636
françois romieu4da19632011-01-03 15:07:55 +00002637 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu236b8082008-05-30 16:11:48 +02002638}
2639
françois romieu4da19632011-01-03 15:07:55 +00002640static void rtl8168cp_1_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu867763c2007-08-17 18:21:58 +02002641{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002642 static const struct phy_reg phy_reg_init[] = {
Francois Romieu867763c2007-08-17 18:21:58 +02002643 { 0x1f, 0x0000 },
2644 { 0x1d, 0x0f00 },
2645 { 0x1f, 0x0002 },
2646 { 0x0c, 0x1ec8 },
2647 { 0x1f, 0x0000 }
2648 };
2649
françois romieu4da19632011-01-03 15:07:55 +00002650 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu867763c2007-08-17 18:21:58 +02002651}
2652
françois romieu4da19632011-01-03 15:07:55 +00002653static void rtl8168cp_2_hw_phy_config(struct rtl8169_private *tp)
Francois Romieuef3386f2008-06-29 12:24:30 +02002654{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002655 static const struct phy_reg phy_reg_init[] = {
Francois Romieuef3386f2008-06-29 12:24:30 +02002656 { 0x1f, 0x0001 },
2657 { 0x1d, 0x3d98 },
2658 { 0x1f, 0x0000 }
2659 };
2660
françois romieu4da19632011-01-03 15:07:55 +00002661 rtl_writephy(tp, 0x1f, 0x0000);
2662 rtl_patchphy(tp, 0x14, 1 << 5);
2663 rtl_patchphy(tp, 0x0d, 1 << 5);
Francois Romieuef3386f2008-06-29 12:24:30 +02002664
françois romieu4da19632011-01-03 15:07:55 +00002665 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieuef3386f2008-06-29 12:24:30 +02002666}
2667
françois romieu4da19632011-01-03 15:07:55 +00002668static void rtl8168c_1_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu867763c2007-08-17 18:21:58 +02002669{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002670 static const struct phy_reg phy_reg_init[] = {
Francois Romieua3f80672007-10-18 14:35:11 +02002671 { 0x1f, 0x0001 },
2672 { 0x12, 0x2300 },
Francois Romieu867763c2007-08-17 18:21:58 +02002673 { 0x1f, 0x0002 },
2674 { 0x00, 0x88d4 },
2675 { 0x01, 0x82b1 },
2676 { 0x03, 0x7002 },
2677 { 0x08, 0x9e30 },
2678 { 0x09, 0x01f0 },
2679 { 0x0a, 0x5500 },
2680 { 0x0c, 0x00c8 },
2681 { 0x1f, 0x0003 },
2682 { 0x12, 0xc096 },
2683 { 0x16, 0x000a },
Francois Romieuf50d4272008-05-30 16:07:07 +02002684 { 0x1f, 0x0000 },
2685 { 0x1f, 0x0000 },
2686 { 0x09, 0x2000 },
2687 { 0x09, 0x0000 }
Francois Romieu867763c2007-08-17 18:21:58 +02002688 };
2689
françois romieu4da19632011-01-03 15:07:55 +00002690 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieuf50d4272008-05-30 16:07:07 +02002691
françois romieu4da19632011-01-03 15:07:55 +00002692 rtl_patchphy(tp, 0x14, 1 << 5);
2693 rtl_patchphy(tp, 0x0d, 1 << 5);
2694 rtl_writephy(tp, 0x1f, 0x0000);
Francois Romieu867763c2007-08-17 18:21:58 +02002695}
2696
françois romieu4da19632011-01-03 15:07:55 +00002697static void rtl8168c_2_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu7da97ec2007-10-18 15:20:43 +02002698{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002699 static const struct phy_reg phy_reg_init[] = {
Francois Romieuf50d4272008-05-30 16:07:07 +02002700 { 0x1f, 0x0001 },
Francois Romieu7da97ec2007-10-18 15:20:43 +02002701 { 0x12, 0x2300 },
Francois Romieuf50d4272008-05-30 16:07:07 +02002702 { 0x03, 0x802f },
2703 { 0x02, 0x4f02 },
2704 { 0x01, 0x0409 },
2705 { 0x00, 0xf099 },
2706 { 0x04, 0x9800 },
2707 { 0x04, 0x9000 },
2708 { 0x1d, 0x3d98 },
Francois Romieu7da97ec2007-10-18 15:20:43 +02002709 { 0x1f, 0x0002 },
2710 { 0x0c, 0x7eb8 },
Francois Romieuf50d4272008-05-30 16:07:07 +02002711 { 0x06, 0x0761 },
2712 { 0x1f, 0x0003 },
2713 { 0x16, 0x0f0a },
Francois Romieu7da97ec2007-10-18 15:20:43 +02002714 { 0x1f, 0x0000 }
2715 };
2716
françois romieu4da19632011-01-03 15:07:55 +00002717 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieuf50d4272008-05-30 16:07:07 +02002718
françois romieu4da19632011-01-03 15:07:55 +00002719 rtl_patchphy(tp, 0x16, 1 << 0);
2720 rtl_patchphy(tp, 0x14, 1 << 5);
2721 rtl_patchphy(tp, 0x0d, 1 << 5);
2722 rtl_writephy(tp, 0x1f, 0x0000);
Francois Romieu7da97ec2007-10-18 15:20:43 +02002723}
2724
françois romieu4da19632011-01-03 15:07:55 +00002725static void rtl8168c_3_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu197ff762008-06-28 13:16:02 +02002726{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002727 static const struct phy_reg phy_reg_init[] = {
Francois Romieu197ff762008-06-28 13:16:02 +02002728 { 0x1f, 0x0001 },
2729 { 0x12, 0x2300 },
2730 { 0x1d, 0x3d98 },
2731 { 0x1f, 0x0002 },
2732 { 0x0c, 0x7eb8 },
2733 { 0x06, 0x5461 },
2734 { 0x1f, 0x0003 },
2735 { 0x16, 0x0f0a },
2736 { 0x1f, 0x0000 }
2737 };
2738
françois romieu4da19632011-01-03 15:07:55 +00002739 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu197ff762008-06-28 13:16:02 +02002740
françois romieu4da19632011-01-03 15:07:55 +00002741 rtl_patchphy(tp, 0x16, 1 << 0);
2742 rtl_patchphy(tp, 0x14, 1 << 5);
2743 rtl_patchphy(tp, 0x0d, 1 << 5);
2744 rtl_writephy(tp, 0x1f, 0x0000);
Francois Romieu197ff762008-06-28 13:16:02 +02002745}
2746
françois romieu4da19632011-01-03 15:07:55 +00002747static void rtl8168c_4_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu6fb07052008-06-29 11:54:28 +02002748{
françois romieu4da19632011-01-03 15:07:55 +00002749 rtl8168c_3_hw_phy_config(tp);
Francois Romieu6fb07052008-06-29 11:54:28 +02002750}
2751
françois romieubca03d52011-01-03 15:07:31 +00002752static void rtl8168d_1_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu5b538df2008-07-20 16:22:45 +02002753{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002754 static const struct phy_reg phy_reg_init_0[] = {
françois romieubca03d52011-01-03 15:07:31 +00002755 /* Channel Estimation */
Francois Romieu5b538df2008-07-20 16:22:45 +02002756 { 0x1f, 0x0001 },
françois romieudaf9df62009-10-07 12:44:20 +00002757 { 0x06, 0x4064 },
2758 { 0x07, 0x2863 },
2759 { 0x08, 0x059c },
2760 { 0x09, 0x26b4 },
2761 { 0x0a, 0x6a19 },
2762 { 0x0b, 0xdcc8 },
2763 { 0x10, 0xf06d },
2764 { 0x14, 0x7f68 },
2765 { 0x18, 0x7fd9 },
2766 { 0x1c, 0xf0ff },
2767 { 0x1d, 0x3d9c },
Francois Romieu5b538df2008-07-20 16:22:45 +02002768 { 0x1f, 0x0003 },
françois romieudaf9df62009-10-07 12:44:20 +00002769 { 0x12, 0xf49f },
2770 { 0x13, 0x070b },
2771 { 0x1a, 0x05ad },
françois romieubca03d52011-01-03 15:07:31 +00002772 { 0x14, 0x94c0 },
2773
2774 /*
2775 * Tx Error Issue
Francois Romieucecb5fd2011-04-01 10:21:07 +02002776 * Enhance line driver power
françois romieubca03d52011-01-03 15:07:31 +00002777 */
Francois Romieu5b538df2008-07-20 16:22:45 +02002778 { 0x1f, 0x0002 },
françois romieudaf9df62009-10-07 12:44:20 +00002779 { 0x06, 0x5561 },
Francois Romieu5b538df2008-07-20 16:22:45 +02002780 { 0x1f, 0x0005 },
françois romieudaf9df62009-10-07 12:44:20 +00002781 { 0x05, 0x8332 },
françois romieubca03d52011-01-03 15:07:31 +00002782 { 0x06, 0x5561 },
2783
2784 /*
2785 * Can not link to 1Gbps with bad cable
2786 * Decrease SNR threshold form 21.07dB to 19.04dB
2787 */
2788 { 0x1f, 0x0001 },
2789 { 0x17, 0x0cc0 },
françois romieudaf9df62009-10-07 12:44:20 +00002790
2791 { 0x1f, 0x0000 },
françois romieubca03d52011-01-03 15:07:31 +00002792 { 0x0d, 0xf880 }
Francois Romieu5b538df2008-07-20 16:22:45 +02002793 };
2794
françois romieu4da19632011-01-03 15:07:55 +00002795 rtl_writephy_batch(tp, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0));
Francois Romieu5b538df2008-07-20 16:22:45 +02002796
françois romieubca03d52011-01-03 15:07:31 +00002797 /*
2798 * Rx Error Issue
2799 * Fine Tune Switching regulator parameter
2800 */
françois romieu4da19632011-01-03 15:07:55 +00002801 rtl_writephy(tp, 0x1f, 0x0002);
2802 rtl_w1w0_phy(tp, 0x0b, 0x0010, 0x00ef);
2803 rtl_w1w0_phy(tp, 0x0c, 0xa200, 0x5d00);
françois romieudaf9df62009-10-07 12:44:20 +00002804
Francois Romieufdf6fc02012-07-06 22:40:38 +02002805 if (rtl8168d_efuse_read(tp, 0x01) == 0xb1) {
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002806 static const struct phy_reg phy_reg_init[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002807 { 0x1f, 0x0002 },
2808 { 0x05, 0x669a },
Francois Romieu5b538df2008-07-20 16:22:45 +02002809 { 0x1f, 0x0005 },
françois romieudaf9df62009-10-07 12:44:20 +00002810 { 0x05, 0x8330 },
2811 { 0x06, 0x669a },
2812 { 0x1f, 0x0002 }
2813 };
2814 int val;
2815
françois romieu4da19632011-01-03 15:07:55 +00002816 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieudaf9df62009-10-07 12:44:20 +00002817
françois romieu4da19632011-01-03 15:07:55 +00002818 val = rtl_readphy(tp, 0x0d);
françois romieudaf9df62009-10-07 12:44:20 +00002819
2820 if ((val & 0x00ff) != 0x006c) {
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002821 static const u32 set[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002822 0x0065, 0x0066, 0x0067, 0x0068,
2823 0x0069, 0x006a, 0x006b, 0x006c
2824 };
2825 int i;
2826
françois romieu4da19632011-01-03 15:07:55 +00002827 rtl_writephy(tp, 0x1f, 0x0002);
françois romieudaf9df62009-10-07 12:44:20 +00002828
2829 val &= 0xff00;
2830 for (i = 0; i < ARRAY_SIZE(set); i++)
françois romieu4da19632011-01-03 15:07:55 +00002831 rtl_writephy(tp, 0x0d, val | set[i]);
françois romieudaf9df62009-10-07 12:44:20 +00002832 }
2833 } else {
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002834 static const struct phy_reg phy_reg_init[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002835 { 0x1f, 0x0002 },
2836 { 0x05, 0x6662 },
Francois Romieu5b538df2008-07-20 16:22:45 +02002837 { 0x1f, 0x0005 },
françois romieudaf9df62009-10-07 12:44:20 +00002838 { 0x05, 0x8330 },
2839 { 0x06, 0x6662 }
Francois Romieu5b538df2008-07-20 16:22:45 +02002840 };
2841
françois romieu4da19632011-01-03 15:07:55 +00002842 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu5b538df2008-07-20 16:22:45 +02002843 }
2844
françois romieubca03d52011-01-03 15:07:31 +00002845 /* RSET couple improve */
françois romieu4da19632011-01-03 15:07:55 +00002846 rtl_writephy(tp, 0x1f, 0x0002);
2847 rtl_patchphy(tp, 0x0d, 0x0300);
2848 rtl_patchphy(tp, 0x0f, 0x0010);
françois romieudaf9df62009-10-07 12:44:20 +00002849
françois romieubca03d52011-01-03 15:07:31 +00002850 /* Fine tune PLL performance */
françois romieu4da19632011-01-03 15:07:55 +00002851 rtl_writephy(tp, 0x1f, 0x0002);
2852 rtl_w1w0_phy(tp, 0x02, 0x0100, 0x0600);
2853 rtl_w1w0_phy(tp, 0x03, 0x0000, 0xe000);
françois romieudaf9df62009-10-07 12:44:20 +00002854
françois romieu4da19632011-01-03 15:07:55 +00002855 rtl_writephy(tp, 0x1f, 0x0005);
2856 rtl_writephy(tp, 0x05, 0x001b);
François Romieu953a12c2011-04-24 17:38:48 +02002857
2858 rtl_apply_firmware_cond(tp, MII_EXPANSION, 0xbf00);
françois romieubca03d52011-01-03 15:07:31 +00002859
françois romieu4da19632011-01-03 15:07:55 +00002860 rtl_writephy(tp, 0x1f, 0x0000);
françois romieudaf9df62009-10-07 12:44:20 +00002861}
2862
françois romieubca03d52011-01-03 15:07:31 +00002863static void rtl8168d_2_hw_phy_config(struct rtl8169_private *tp)
françois romieudaf9df62009-10-07 12:44:20 +00002864{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002865 static const struct phy_reg phy_reg_init_0[] = {
françois romieubca03d52011-01-03 15:07:31 +00002866 /* Channel Estimation */
françois romieudaf9df62009-10-07 12:44:20 +00002867 { 0x1f, 0x0001 },
2868 { 0x06, 0x4064 },
2869 { 0x07, 0x2863 },
2870 { 0x08, 0x059c },
2871 { 0x09, 0x26b4 },
2872 { 0x0a, 0x6a19 },
2873 { 0x0b, 0xdcc8 },
2874 { 0x10, 0xf06d },
2875 { 0x14, 0x7f68 },
2876 { 0x18, 0x7fd9 },
2877 { 0x1c, 0xf0ff },
2878 { 0x1d, 0x3d9c },
2879 { 0x1f, 0x0003 },
2880 { 0x12, 0xf49f },
2881 { 0x13, 0x070b },
2882 { 0x1a, 0x05ad },
2883 { 0x14, 0x94c0 },
2884
françois romieubca03d52011-01-03 15:07:31 +00002885 /*
2886 * Tx Error Issue
Francois Romieucecb5fd2011-04-01 10:21:07 +02002887 * Enhance line driver power
françois romieubca03d52011-01-03 15:07:31 +00002888 */
françois romieudaf9df62009-10-07 12:44:20 +00002889 { 0x1f, 0x0002 },
2890 { 0x06, 0x5561 },
2891 { 0x1f, 0x0005 },
2892 { 0x05, 0x8332 },
françois romieubca03d52011-01-03 15:07:31 +00002893 { 0x06, 0x5561 },
2894
2895 /*
2896 * Can not link to 1Gbps with bad cable
2897 * Decrease SNR threshold form 21.07dB to 19.04dB
2898 */
2899 { 0x1f, 0x0001 },
2900 { 0x17, 0x0cc0 },
françois romieudaf9df62009-10-07 12:44:20 +00002901
2902 { 0x1f, 0x0000 },
françois romieubca03d52011-01-03 15:07:31 +00002903 { 0x0d, 0xf880 }
françois romieudaf9df62009-10-07 12:44:20 +00002904 };
2905
françois romieu4da19632011-01-03 15:07:55 +00002906 rtl_writephy_batch(tp, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0));
françois romieudaf9df62009-10-07 12:44:20 +00002907
Francois Romieufdf6fc02012-07-06 22:40:38 +02002908 if (rtl8168d_efuse_read(tp, 0x01) == 0xb1) {
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002909 static const struct phy_reg phy_reg_init[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002910 { 0x1f, 0x0002 },
2911 { 0x05, 0x669a },
2912 { 0x1f, 0x0005 },
2913 { 0x05, 0x8330 },
2914 { 0x06, 0x669a },
2915
2916 { 0x1f, 0x0002 }
2917 };
2918 int val;
2919
françois romieu4da19632011-01-03 15:07:55 +00002920 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieudaf9df62009-10-07 12:44:20 +00002921
françois romieu4da19632011-01-03 15:07:55 +00002922 val = rtl_readphy(tp, 0x0d);
françois romieudaf9df62009-10-07 12:44:20 +00002923 if ((val & 0x00ff) != 0x006c) {
Joe Perchesb6bc7652010-12-21 02:16:08 -08002924 static const u32 set[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002925 0x0065, 0x0066, 0x0067, 0x0068,
2926 0x0069, 0x006a, 0x006b, 0x006c
2927 };
2928 int i;
2929
françois romieu4da19632011-01-03 15:07:55 +00002930 rtl_writephy(tp, 0x1f, 0x0002);
françois romieudaf9df62009-10-07 12:44:20 +00002931
2932 val &= 0xff00;
2933 for (i = 0; i < ARRAY_SIZE(set); i++)
françois romieu4da19632011-01-03 15:07:55 +00002934 rtl_writephy(tp, 0x0d, val | set[i]);
françois romieudaf9df62009-10-07 12:44:20 +00002935 }
2936 } else {
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002937 static const struct phy_reg phy_reg_init[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002938 { 0x1f, 0x0002 },
2939 { 0x05, 0x2642 },
2940 { 0x1f, 0x0005 },
2941 { 0x05, 0x8330 },
2942 { 0x06, 0x2642 }
2943 };
2944
françois romieu4da19632011-01-03 15:07:55 +00002945 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
françois romieudaf9df62009-10-07 12:44:20 +00002946 }
2947
françois romieubca03d52011-01-03 15:07:31 +00002948 /* Fine tune PLL performance */
françois romieu4da19632011-01-03 15:07:55 +00002949 rtl_writephy(tp, 0x1f, 0x0002);
2950 rtl_w1w0_phy(tp, 0x02, 0x0100, 0x0600);
2951 rtl_w1w0_phy(tp, 0x03, 0x0000, 0xe000);
françois romieudaf9df62009-10-07 12:44:20 +00002952
françois romieubca03d52011-01-03 15:07:31 +00002953 /* Switching regulator Slew rate */
françois romieu4da19632011-01-03 15:07:55 +00002954 rtl_writephy(tp, 0x1f, 0x0002);
2955 rtl_patchphy(tp, 0x0f, 0x0017);
françois romieudaf9df62009-10-07 12:44:20 +00002956
françois romieu4da19632011-01-03 15:07:55 +00002957 rtl_writephy(tp, 0x1f, 0x0005);
2958 rtl_writephy(tp, 0x05, 0x001b);
François Romieu953a12c2011-04-24 17:38:48 +02002959
2960 rtl_apply_firmware_cond(tp, MII_EXPANSION, 0xb300);
françois romieubca03d52011-01-03 15:07:31 +00002961
françois romieu4da19632011-01-03 15:07:55 +00002962 rtl_writephy(tp, 0x1f, 0x0000);
françois romieudaf9df62009-10-07 12:44:20 +00002963}
2964
françois romieu4da19632011-01-03 15:07:55 +00002965static void rtl8168d_3_hw_phy_config(struct rtl8169_private *tp)
françois romieudaf9df62009-10-07 12:44:20 +00002966{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08002967 static const struct phy_reg phy_reg_init[] = {
françois romieudaf9df62009-10-07 12:44:20 +00002968 { 0x1f, 0x0002 },
2969 { 0x10, 0x0008 },
2970 { 0x0d, 0x006c },
2971
2972 { 0x1f, 0x0000 },
2973 { 0x0d, 0xf880 },
2974
2975 { 0x1f, 0x0001 },
2976 { 0x17, 0x0cc0 },
2977
2978 { 0x1f, 0x0001 },
2979 { 0x0b, 0xa4d8 },
2980 { 0x09, 0x281c },
2981 { 0x07, 0x2883 },
2982 { 0x0a, 0x6b35 },
2983 { 0x1d, 0x3da4 },
2984 { 0x1c, 0xeffd },
2985 { 0x14, 0x7f52 },
2986 { 0x18, 0x7fc6 },
2987 { 0x08, 0x0601 },
2988 { 0x06, 0x4063 },
2989 { 0x10, 0xf074 },
2990 { 0x1f, 0x0003 },
2991 { 0x13, 0x0789 },
2992 { 0x12, 0xf4bd },
2993 { 0x1a, 0x04fd },
2994 { 0x14, 0x84b0 },
2995 { 0x1f, 0x0000 },
2996 { 0x00, 0x9200 },
2997
2998 { 0x1f, 0x0005 },
2999 { 0x01, 0x0340 },
3000 { 0x1f, 0x0001 },
3001 { 0x04, 0x4000 },
3002 { 0x03, 0x1d21 },
3003 { 0x02, 0x0c32 },
3004 { 0x01, 0x0200 },
3005 { 0x00, 0x5554 },
3006 { 0x04, 0x4800 },
3007 { 0x04, 0x4000 },
3008 { 0x04, 0xf000 },
3009 { 0x03, 0xdf01 },
3010 { 0x02, 0xdf20 },
3011 { 0x01, 0x101a },
3012 { 0x00, 0xa0ff },
3013 { 0x04, 0xf800 },
3014 { 0x04, 0xf000 },
3015 { 0x1f, 0x0000 },
3016
3017 { 0x1f, 0x0007 },
3018 { 0x1e, 0x0023 },
3019 { 0x16, 0x0000 },
3020 { 0x1f, 0x0000 }
3021 };
3022
françois romieu4da19632011-01-03 15:07:55 +00003023 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu5b538df2008-07-20 16:22:45 +02003024}
3025
françois romieue6de30d2011-01-03 15:08:37 +00003026static void rtl8168d_4_hw_phy_config(struct rtl8169_private *tp)
3027{
3028 static const struct phy_reg phy_reg_init[] = {
3029 { 0x1f, 0x0001 },
3030 { 0x17, 0x0cc0 },
3031
3032 { 0x1f, 0x0007 },
3033 { 0x1e, 0x002d },
3034 { 0x18, 0x0040 },
3035 { 0x1f, 0x0000 }
3036 };
3037
3038 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3039 rtl_patchphy(tp, 0x0d, 1 << 5);
3040}
3041
Hayes Wang70090422011-07-06 15:58:06 +08003042static void rtl8168e_1_hw_phy_config(struct rtl8169_private *tp)
hayeswang01dc7fe2011-03-21 01:50:28 +00003043{
3044 static const struct phy_reg phy_reg_init[] = {
3045 /* Enable Delay cap */
3046 { 0x1f, 0x0005 },
3047 { 0x05, 0x8b80 },
3048 { 0x06, 0xc896 },
3049 { 0x1f, 0x0000 },
3050
3051 /* Channel estimation fine tune */
3052 { 0x1f, 0x0001 },
3053 { 0x0b, 0x6c20 },
3054 { 0x07, 0x2872 },
3055 { 0x1c, 0xefff },
3056 { 0x1f, 0x0003 },
3057 { 0x14, 0x6420 },
3058 { 0x1f, 0x0000 },
3059
3060 /* Update PFM & 10M TX idle timer */
3061 { 0x1f, 0x0007 },
3062 { 0x1e, 0x002f },
3063 { 0x15, 0x1919 },
3064 { 0x1f, 0x0000 },
3065
3066 { 0x1f, 0x0007 },
3067 { 0x1e, 0x00ac },
3068 { 0x18, 0x0006 },
3069 { 0x1f, 0x0000 }
3070 };
3071
Francois Romieu15ecd032011-04-27 13:52:22 -07003072 rtl_apply_firmware(tp);
3073
hayeswang01dc7fe2011-03-21 01:50:28 +00003074 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3075
3076 /* DCO enable for 10M IDLE Power */
3077 rtl_writephy(tp, 0x1f, 0x0007);
3078 rtl_writephy(tp, 0x1e, 0x0023);
3079 rtl_w1w0_phy(tp, 0x17, 0x0006, 0x0000);
3080 rtl_writephy(tp, 0x1f, 0x0000);
3081
3082 /* For impedance matching */
3083 rtl_writephy(tp, 0x1f, 0x0002);
3084 rtl_w1w0_phy(tp, 0x08, 0x8000, 0x7f00);
Francois Romieucecb5fd2011-04-01 10:21:07 +02003085 rtl_writephy(tp, 0x1f, 0x0000);
hayeswang01dc7fe2011-03-21 01:50:28 +00003086
3087 /* PHY auto speed down */
3088 rtl_writephy(tp, 0x1f, 0x0007);
3089 rtl_writephy(tp, 0x1e, 0x002d);
3090 rtl_w1w0_phy(tp, 0x18, 0x0050, 0x0000);
3091 rtl_writephy(tp, 0x1f, 0x0000);
3092 rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000);
3093
3094 rtl_writephy(tp, 0x1f, 0x0005);
3095 rtl_writephy(tp, 0x05, 0x8b86);
3096 rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000);
3097 rtl_writephy(tp, 0x1f, 0x0000);
3098
3099 rtl_writephy(tp, 0x1f, 0x0005);
3100 rtl_writephy(tp, 0x05, 0x8b85);
3101 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x2000);
3102 rtl_writephy(tp, 0x1f, 0x0007);
3103 rtl_writephy(tp, 0x1e, 0x0020);
3104 rtl_w1w0_phy(tp, 0x15, 0x0000, 0x1100);
3105 rtl_writephy(tp, 0x1f, 0x0006);
3106 rtl_writephy(tp, 0x00, 0x5a00);
3107 rtl_writephy(tp, 0x1f, 0x0000);
3108 rtl_writephy(tp, 0x0d, 0x0007);
3109 rtl_writephy(tp, 0x0e, 0x003c);
3110 rtl_writephy(tp, 0x0d, 0x4007);
3111 rtl_writephy(tp, 0x0e, 0x0000);
3112 rtl_writephy(tp, 0x0d, 0x0000);
3113}
3114
françois romieu9ecb9aa2012-12-07 11:20:21 +00003115static void rtl_rar_exgmac_set(struct rtl8169_private *tp, u8 *addr)
3116{
3117 const u16 w[] = {
3118 addr[0] | (addr[1] << 8),
3119 addr[2] | (addr[3] << 8),
3120 addr[4] | (addr[5] << 8)
3121 };
3122 const struct exgmac_reg e[] = {
3123 { .addr = 0xe0, ERIAR_MASK_1111, .val = w[0] | (w[1] << 16) },
3124 { .addr = 0xe4, ERIAR_MASK_1111, .val = w[2] },
3125 { .addr = 0xf0, ERIAR_MASK_1111, .val = w[0] << 16 },
3126 { .addr = 0xf4, ERIAR_MASK_1111, .val = w[1] | (w[2] << 16) }
3127 };
3128
3129 rtl_write_exgmac_batch(tp, e, ARRAY_SIZE(e));
3130}
3131
Hayes Wang70090422011-07-06 15:58:06 +08003132static void rtl8168e_2_hw_phy_config(struct rtl8169_private *tp)
3133{
3134 static const struct phy_reg phy_reg_init[] = {
3135 /* Enable Delay cap */
3136 { 0x1f, 0x0004 },
3137 { 0x1f, 0x0007 },
3138 { 0x1e, 0x00ac },
3139 { 0x18, 0x0006 },
3140 { 0x1f, 0x0002 },
3141 { 0x1f, 0x0000 },
3142 { 0x1f, 0x0000 },
3143
3144 /* Channel estimation fine tune */
3145 { 0x1f, 0x0003 },
3146 { 0x09, 0xa20f },
3147 { 0x1f, 0x0000 },
3148 { 0x1f, 0x0000 },
3149
3150 /* Green Setting */
3151 { 0x1f, 0x0005 },
3152 { 0x05, 0x8b5b },
3153 { 0x06, 0x9222 },
3154 { 0x05, 0x8b6d },
3155 { 0x06, 0x8000 },
3156 { 0x05, 0x8b76 },
3157 { 0x06, 0x8000 },
3158 { 0x1f, 0x0000 }
3159 };
3160
3161 rtl_apply_firmware(tp);
3162
3163 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3164
3165 /* For 4-corner performance improve */
3166 rtl_writephy(tp, 0x1f, 0x0005);
3167 rtl_writephy(tp, 0x05, 0x8b80);
3168 rtl_w1w0_phy(tp, 0x17, 0x0006, 0x0000);
3169 rtl_writephy(tp, 0x1f, 0x0000);
3170
3171 /* PHY auto speed down */
3172 rtl_writephy(tp, 0x1f, 0x0004);
3173 rtl_writephy(tp, 0x1f, 0x0007);
3174 rtl_writephy(tp, 0x1e, 0x002d);
3175 rtl_w1w0_phy(tp, 0x18, 0x0010, 0x0000);
3176 rtl_writephy(tp, 0x1f, 0x0002);
3177 rtl_writephy(tp, 0x1f, 0x0000);
3178 rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000);
3179
3180 /* improve 10M EEE waveform */
3181 rtl_writephy(tp, 0x1f, 0x0005);
3182 rtl_writephy(tp, 0x05, 0x8b86);
3183 rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000);
3184 rtl_writephy(tp, 0x1f, 0x0000);
3185
3186 /* Improve 2-pair detection performance */
3187 rtl_writephy(tp, 0x1f, 0x0005);
3188 rtl_writephy(tp, 0x05, 0x8b85);
3189 rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000);
3190 rtl_writephy(tp, 0x1f, 0x0000);
3191
3192 /* EEE setting */
Francois Romieufdf6fc02012-07-06 22:40:38 +02003193 rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_1111, 0x0000, 0x0003, ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08003194 rtl_writephy(tp, 0x1f, 0x0005);
3195 rtl_writephy(tp, 0x05, 0x8b85);
3196 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x2000);
3197 rtl_writephy(tp, 0x1f, 0x0004);
3198 rtl_writephy(tp, 0x1f, 0x0007);
3199 rtl_writephy(tp, 0x1e, 0x0020);
David S. Miller1805b2f2011-10-24 18:18:09 -04003200 rtl_w1w0_phy(tp, 0x15, 0x0000, 0x0100);
Hayes Wang70090422011-07-06 15:58:06 +08003201 rtl_writephy(tp, 0x1f, 0x0002);
3202 rtl_writephy(tp, 0x1f, 0x0000);
3203 rtl_writephy(tp, 0x0d, 0x0007);
3204 rtl_writephy(tp, 0x0e, 0x003c);
3205 rtl_writephy(tp, 0x0d, 0x4007);
3206 rtl_writephy(tp, 0x0e, 0x0000);
3207 rtl_writephy(tp, 0x0d, 0x0000);
3208
3209 /* Green feature */
3210 rtl_writephy(tp, 0x1f, 0x0003);
3211 rtl_w1w0_phy(tp, 0x19, 0x0000, 0x0001);
3212 rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0400);
3213 rtl_writephy(tp, 0x1f, 0x0000);
hayeswange0c07552012-10-23 20:24:03 +00003214
françois romieu9ecb9aa2012-12-07 11:20:21 +00003215 /* Broken BIOS workaround: feed GigaMAC registers with MAC address. */
3216 rtl_rar_exgmac_set(tp, tp->dev->dev_addr);
Hayes Wang70090422011-07-06 15:58:06 +08003217}
3218
Hayes Wang5f886e02012-03-30 14:33:03 +08003219static void rtl8168f_hw_phy_config(struct rtl8169_private *tp)
3220{
3221 /* For 4-corner performance improve */
3222 rtl_writephy(tp, 0x1f, 0x0005);
3223 rtl_writephy(tp, 0x05, 0x8b80);
3224 rtl_w1w0_phy(tp, 0x06, 0x0006, 0x0000);
3225 rtl_writephy(tp, 0x1f, 0x0000);
3226
3227 /* PHY auto speed down */
3228 rtl_writephy(tp, 0x1f, 0x0007);
3229 rtl_writephy(tp, 0x1e, 0x002d);
3230 rtl_w1w0_phy(tp, 0x18, 0x0010, 0x0000);
3231 rtl_writephy(tp, 0x1f, 0x0000);
3232 rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000);
3233
3234 /* Improve 10M EEE waveform */
3235 rtl_writephy(tp, 0x1f, 0x0005);
3236 rtl_writephy(tp, 0x05, 0x8b86);
3237 rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000);
3238 rtl_writephy(tp, 0x1f, 0x0000);
3239}
3240
Hayes Wangc2218922011-09-06 16:55:18 +08003241static void rtl8168f_1_hw_phy_config(struct rtl8169_private *tp)
3242{
3243 static const struct phy_reg phy_reg_init[] = {
3244 /* Channel estimation fine tune */
3245 { 0x1f, 0x0003 },
3246 { 0x09, 0xa20f },
3247 { 0x1f, 0x0000 },
3248
3249 /* Modify green table for giga & fnet */
3250 { 0x1f, 0x0005 },
3251 { 0x05, 0x8b55 },
3252 { 0x06, 0x0000 },
3253 { 0x05, 0x8b5e },
3254 { 0x06, 0x0000 },
3255 { 0x05, 0x8b67 },
3256 { 0x06, 0x0000 },
3257 { 0x05, 0x8b70 },
3258 { 0x06, 0x0000 },
3259 { 0x1f, 0x0000 },
3260 { 0x1f, 0x0007 },
3261 { 0x1e, 0x0078 },
3262 { 0x17, 0x0000 },
3263 { 0x19, 0x00fb },
3264 { 0x1f, 0x0000 },
3265
3266 /* Modify green table for 10M */
3267 { 0x1f, 0x0005 },
3268 { 0x05, 0x8b79 },
3269 { 0x06, 0xaa00 },
3270 { 0x1f, 0x0000 },
3271
3272 /* Disable hiimpedance detection (RTCT) */
3273 { 0x1f, 0x0003 },
3274 { 0x01, 0x328a },
3275 { 0x1f, 0x0000 }
3276 };
3277
3278 rtl_apply_firmware(tp);
3279
3280 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3281
Hayes Wang5f886e02012-03-30 14:33:03 +08003282 rtl8168f_hw_phy_config(tp);
Hayes Wangc2218922011-09-06 16:55:18 +08003283
3284 /* Improve 2-pair detection performance */
3285 rtl_writephy(tp, 0x1f, 0x0005);
3286 rtl_writephy(tp, 0x05, 0x8b85);
3287 rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000);
3288 rtl_writephy(tp, 0x1f, 0x0000);
3289}
3290
3291static void rtl8168f_2_hw_phy_config(struct rtl8169_private *tp)
3292{
3293 rtl_apply_firmware(tp);
3294
Hayes Wang5f886e02012-03-30 14:33:03 +08003295 rtl8168f_hw_phy_config(tp);
Hayes Wangc2218922011-09-06 16:55:18 +08003296}
3297
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003298static void rtl8411_hw_phy_config(struct rtl8169_private *tp)
3299{
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003300 static const struct phy_reg phy_reg_init[] = {
3301 /* Channel estimation fine tune */
3302 { 0x1f, 0x0003 },
3303 { 0x09, 0xa20f },
3304 { 0x1f, 0x0000 },
3305
3306 /* Modify green table for giga & fnet */
3307 { 0x1f, 0x0005 },
3308 { 0x05, 0x8b55 },
3309 { 0x06, 0x0000 },
3310 { 0x05, 0x8b5e },
3311 { 0x06, 0x0000 },
3312 { 0x05, 0x8b67 },
3313 { 0x06, 0x0000 },
3314 { 0x05, 0x8b70 },
3315 { 0x06, 0x0000 },
3316 { 0x1f, 0x0000 },
3317 { 0x1f, 0x0007 },
3318 { 0x1e, 0x0078 },
3319 { 0x17, 0x0000 },
3320 { 0x19, 0x00aa },
3321 { 0x1f, 0x0000 },
3322
3323 /* Modify green table for 10M */
3324 { 0x1f, 0x0005 },
3325 { 0x05, 0x8b79 },
3326 { 0x06, 0xaa00 },
3327 { 0x1f, 0x0000 },
3328
3329 /* Disable hiimpedance detection (RTCT) */
3330 { 0x1f, 0x0003 },
3331 { 0x01, 0x328a },
3332 { 0x1f, 0x0000 }
3333 };
3334
3335
3336 rtl_apply_firmware(tp);
3337
3338 rtl8168f_hw_phy_config(tp);
3339
3340 /* Improve 2-pair detection performance */
3341 rtl_writephy(tp, 0x1f, 0x0005);
3342 rtl_writephy(tp, 0x05, 0x8b85);
3343 rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000);
3344 rtl_writephy(tp, 0x1f, 0x0000);
3345
3346 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3347
3348 /* Modify green table for giga */
3349 rtl_writephy(tp, 0x1f, 0x0005);
3350 rtl_writephy(tp, 0x05, 0x8b54);
3351 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0800);
3352 rtl_writephy(tp, 0x05, 0x8b5d);
3353 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0800);
3354 rtl_writephy(tp, 0x05, 0x8a7c);
3355 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100);
3356 rtl_writephy(tp, 0x05, 0x8a7f);
3357 rtl_w1w0_phy(tp, 0x06, 0x0100, 0x0000);
3358 rtl_writephy(tp, 0x05, 0x8a82);
3359 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100);
3360 rtl_writephy(tp, 0x05, 0x8a85);
3361 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100);
3362 rtl_writephy(tp, 0x05, 0x8a88);
3363 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100);
3364 rtl_writephy(tp, 0x1f, 0x0000);
3365
3366 /* uc same-seed solution */
3367 rtl_writephy(tp, 0x1f, 0x0005);
3368 rtl_writephy(tp, 0x05, 0x8b85);
3369 rtl_w1w0_phy(tp, 0x06, 0x8000, 0x0000);
3370 rtl_writephy(tp, 0x1f, 0x0000);
3371
3372 /* eee setting */
Francois Romieufdf6fc02012-07-06 22:40:38 +02003373 rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_0001, 0x00, 0x03, ERIAR_EXGMAC);
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003374 rtl_writephy(tp, 0x1f, 0x0005);
3375 rtl_writephy(tp, 0x05, 0x8b85);
3376 rtl_w1w0_phy(tp, 0x06, 0x0000, 0x2000);
3377 rtl_writephy(tp, 0x1f, 0x0004);
3378 rtl_writephy(tp, 0x1f, 0x0007);
3379 rtl_writephy(tp, 0x1e, 0x0020);
3380 rtl_w1w0_phy(tp, 0x15, 0x0000, 0x0100);
3381 rtl_writephy(tp, 0x1f, 0x0000);
3382 rtl_writephy(tp, 0x0d, 0x0007);
3383 rtl_writephy(tp, 0x0e, 0x003c);
3384 rtl_writephy(tp, 0x0d, 0x4007);
3385 rtl_writephy(tp, 0x0e, 0x0000);
3386 rtl_writephy(tp, 0x0d, 0x0000);
3387
3388 /* Green feature */
3389 rtl_writephy(tp, 0x1f, 0x0003);
3390 rtl_w1w0_phy(tp, 0x19, 0x0000, 0x0001);
3391 rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0400);
3392 rtl_writephy(tp, 0x1f, 0x0000);
3393}
3394
Hayes Wangc5583862012-07-02 17:23:22 +08003395static void rtl8168g_1_hw_phy_config(struct rtl8169_private *tp)
3396{
Hayes Wangc5583862012-07-02 17:23:22 +08003397 rtl_apply_firmware(tp);
3398
hayeswang41f44d12013-04-01 22:23:36 +00003399 rtl_writephy(tp, 0x1f, 0x0a46);
3400 if (rtl_readphy(tp, 0x10) & 0x0100) {
3401 rtl_writephy(tp, 0x1f, 0x0bcc);
3402 rtl_w1w0_phy(tp, 0x12, 0x0000, 0x8000);
3403 } else {
3404 rtl_writephy(tp, 0x1f, 0x0bcc);
3405 rtl_w1w0_phy(tp, 0x12, 0x8000, 0x0000);
3406 }
Hayes Wangc5583862012-07-02 17:23:22 +08003407
hayeswang41f44d12013-04-01 22:23:36 +00003408 rtl_writephy(tp, 0x1f, 0x0a46);
3409 if (rtl_readphy(tp, 0x13) & 0x0100) {
3410 rtl_writephy(tp, 0x1f, 0x0c41);
3411 rtl_w1w0_phy(tp, 0x15, 0x0002, 0x0000);
3412 } else {
hayeswangfe7524c2013-04-01 22:23:37 +00003413 rtl_writephy(tp, 0x1f, 0x0c41);
3414 rtl_w1w0_phy(tp, 0x15, 0x0000, 0x0002);
hayeswang41f44d12013-04-01 22:23:36 +00003415 }
Hayes Wangc5583862012-07-02 17:23:22 +08003416
hayeswang41f44d12013-04-01 22:23:36 +00003417 /* Enable PHY auto speed down */
3418 rtl_writephy(tp, 0x1f, 0x0a44);
3419 rtl_w1w0_phy(tp, 0x11, 0x000c, 0x0000);
Hayes Wangc5583862012-07-02 17:23:22 +08003420
hayeswangfe7524c2013-04-01 22:23:37 +00003421 rtl_writephy(tp, 0x1f, 0x0bcc);
3422 rtl_w1w0_phy(tp, 0x14, 0x0100, 0x0000);
3423 rtl_writephy(tp, 0x1f, 0x0a44);
3424 rtl_w1w0_phy(tp, 0x11, 0x00c0, 0x0000);
3425 rtl_writephy(tp, 0x1f, 0x0a43);
3426 rtl_writephy(tp, 0x13, 0x8084);
3427 rtl_w1w0_phy(tp, 0x14, 0x0000, 0x6000);
3428 rtl_w1w0_phy(tp, 0x10, 0x1003, 0x0000);
3429
hayeswang41f44d12013-04-01 22:23:36 +00003430 /* EEE auto-fallback function */
3431 rtl_writephy(tp, 0x1f, 0x0a4b);
3432 rtl_w1w0_phy(tp, 0x11, 0x0004, 0x0000);
Hayes Wangc5583862012-07-02 17:23:22 +08003433
hayeswang41f44d12013-04-01 22:23:36 +00003434 /* Enable UC LPF tune function */
3435 rtl_writephy(tp, 0x1f, 0x0a43);
3436 rtl_writephy(tp, 0x13, 0x8012);
3437 rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000);
3438
3439 rtl_writephy(tp, 0x1f, 0x0c42);
3440 rtl_w1w0_phy(tp, 0x11, 0x4000, 0x2000);
3441
hayeswangfe7524c2013-04-01 22:23:37 +00003442 /* Improve SWR Efficiency */
3443 rtl_writephy(tp, 0x1f, 0x0bcd);
3444 rtl_writephy(tp, 0x14, 0x5065);
3445 rtl_writephy(tp, 0x14, 0xd065);
3446 rtl_writephy(tp, 0x1f, 0x0bc8);
3447 rtl_writephy(tp, 0x11, 0x5655);
3448 rtl_writephy(tp, 0x1f, 0x0bcd);
3449 rtl_writephy(tp, 0x14, 0x1065);
3450 rtl_writephy(tp, 0x14, 0x9065);
3451 rtl_writephy(tp, 0x14, 0x1065);
3452
David Chang1bac1072013-11-27 15:48:36 +08003453 /* Check ALDPS bit, disable it if enabled */
3454 rtl_writephy(tp, 0x1f, 0x0a43);
3455 if (rtl_readphy(tp, 0x10) & 0x0004)
3456 rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0004);
3457
hayeswang41f44d12013-04-01 22:23:36 +00003458 rtl_writephy(tp, 0x1f, 0x0000);
Hayes Wangc5583862012-07-02 17:23:22 +08003459}
3460
hayeswang57538c42013-04-01 22:23:40 +00003461static void rtl8168g_2_hw_phy_config(struct rtl8169_private *tp)
3462{
3463 rtl_apply_firmware(tp);
3464}
3465
françois romieu4da19632011-01-03 15:07:55 +00003466static void rtl8102e_hw_phy_config(struct rtl8169_private *tp)
Francois Romieu2857ffb2008-08-02 21:08:49 +02003467{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08003468 static const struct phy_reg phy_reg_init[] = {
Francois Romieu2857ffb2008-08-02 21:08:49 +02003469 { 0x1f, 0x0003 },
3470 { 0x08, 0x441d },
3471 { 0x01, 0x9100 },
3472 { 0x1f, 0x0000 }
3473 };
3474
françois romieu4da19632011-01-03 15:07:55 +00003475 rtl_writephy(tp, 0x1f, 0x0000);
3476 rtl_patchphy(tp, 0x11, 1 << 12);
3477 rtl_patchphy(tp, 0x19, 1 << 13);
3478 rtl_patchphy(tp, 0x10, 1 << 15);
Francois Romieu2857ffb2008-08-02 21:08:49 +02003479
françois romieu4da19632011-01-03 15:07:55 +00003480 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
Francois Romieu2857ffb2008-08-02 21:08:49 +02003481}
3482
Hayes Wang5a5e4442011-02-22 17:26:21 +08003483static void rtl8105e_hw_phy_config(struct rtl8169_private *tp)
3484{
3485 static const struct phy_reg phy_reg_init[] = {
3486 { 0x1f, 0x0005 },
3487 { 0x1a, 0x0000 },
3488 { 0x1f, 0x0000 },
3489
3490 { 0x1f, 0x0004 },
3491 { 0x1c, 0x0000 },
3492 { 0x1f, 0x0000 },
3493
3494 { 0x1f, 0x0001 },
3495 { 0x15, 0x7701 },
3496 { 0x1f, 0x0000 }
3497 };
3498
3499 /* Disable ALDPS before ram code */
Francois Romieueef63cc2013-02-08 23:43:20 +01003500 rtl_writephy(tp, 0x1f, 0x0000);
3501 rtl_writephy(tp, 0x18, 0x0310);
3502 msleep(100);
Hayes Wang5a5e4442011-02-22 17:26:21 +08003503
François Romieu953a12c2011-04-24 17:38:48 +02003504 rtl_apply_firmware(tp);
Hayes Wang5a5e4442011-02-22 17:26:21 +08003505
3506 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3507}
3508
Hayes Wang7e18dca2012-03-30 14:33:02 +08003509static void rtl8402_hw_phy_config(struct rtl8169_private *tp)
3510{
Hayes Wang7e18dca2012-03-30 14:33:02 +08003511 /* Disable ALDPS before setting firmware */
Francois Romieueef63cc2013-02-08 23:43:20 +01003512 rtl_writephy(tp, 0x1f, 0x0000);
3513 rtl_writephy(tp, 0x18, 0x0310);
3514 msleep(20);
Hayes Wang7e18dca2012-03-30 14:33:02 +08003515
3516 rtl_apply_firmware(tp);
3517
3518 /* EEE setting */
Francois Romieufdf6fc02012-07-06 22:40:38 +02003519 rtl_eri_write(tp, 0x1b0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
Hayes Wang7e18dca2012-03-30 14:33:02 +08003520 rtl_writephy(tp, 0x1f, 0x0004);
3521 rtl_writephy(tp, 0x10, 0x401f);
3522 rtl_writephy(tp, 0x19, 0x7030);
3523 rtl_writephy(tp, 0x1f, 0x0000);
3524}
3525
Hayes Wang5598bfe2012-07-02 17:23:21 +08003526static void rtl8106e_hw_phy_config(struct rtl8169_private *tp)
3527{
Hayes Wang5598bfe2012-07-02 17:23:21 +08003528 static const struct phy_reg phy_reg_init[] = {
3529 { 0x1f, 0x0004 },
3530 { 0x10, 0xc07f },
3531 { 0x19, 0x7030 },
3532 { 0x1f, 0x0000 }
3533 };
3534
3535 /* Disable ALDPS before ram code */
Francois Romieueef63cc2013-02-08 23:43:20 +01003536 rtl_writephy(tp, 0x1f, 0x0000);
3537 rtl_writephy(tp, 0x18, 0x0310);
3538 msleep(100);
Hayes Wang5598bfe2012-07-02 17:23:21 +08003539
3540 rtl_apply_firmware(tp);
3541
Francois Romieufdf6fc02012-07-06 22:40:38 +02003542 rtl_eri_write(tp, 0x1b0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
Hayes Wang5598bfe2012-07-02 17:23:21 +08003543 rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
3544
Francois Romieufdf6fc02012-07-06 22:40:38 +02003545 rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
Hayes Wang5598bfe2012-07-02 17:23:21 +08003546}
3547
Francois Romieu5615d9f2007-08-17 17:50:46 +02003548static void rtl_hw_phy_config(struct net_device *dev)
3549{
3550 struct rtl8169_private *tp = netdev_priv(dev);
Francois Romieu5615d9f2007-08-17 17:50:46 +02003551
3552 rtl8169_print_mac_version(tp);
3553
3554 switch (tp->mac_version) {
3555 case RTL_GIGA_MAC_VER_01:
3556 break;
3557 case RTL_GIGA_MAC_VER_02:
3558 case RTL_GIGA_MAC_VER_03:
françois romieu4da19632011-01-03 15:07:55 +00003559 rtl8169s_hw_phy_config(tp);
Francois Romieu5615d9f2007-08-17 17:50:46 +02003560 break;
3561 case RTL_GIGA_MAC_VER_04:
françois romieu4da19632011-01-03 15:07:55 +00003562 rtl8169sb_hw_phy_config(tp);
Francois Romieu5615d9f2007-08-17 17:50:46 +02003563 break;
françois romieu2e9558562009-08-10 19:44:19 +00003564 case RTL_GIGA_MAC_VER_05:
françois romieu4da19632011-01-03 15:07:55 +00003565 rtl8169scd_hw_phy_config(tp);
françois romieu2e9558562009-08-10 19:44:19 +00003566 break;
françois romieu8c7006a2009-08-10 19:43:29 +00003567 case RTL_GIGA_MAC_VER_06:
françois romieu4da19632011-01-03 15:07:55 +00003568 rtl8169sce_hw_phy_config(tp);
françois romieu8c7006a2009-08-10 19:43:29 +00003569 break;
Francois Romieu2857ffb2008-08-02 21:08:49 +02003570 case RTL_GIGA_MAC_VER_07:
3571 case RTL_GIGA_MAC_VER_08:
3572 case RTL_GIGA_MAC_VER_09:
françois romieu4da19632011-01-03 15:07:55 +00003573 rtl8102e_hw_phy_config(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02003574 break;
Francois Romieu236b8082008-05-30 16:11:48 +02003575 case RTL_GIGA_MAC_VER_11:
françois romieu4da19632011-01-03 15:07:55 +00003576 rtl8168bb_hw_phy_config(tp);
Francois Romieu236b8082008-05-30 16:11:48 +02003577 break;
3578 case RTL_GIGA_MAC_VER_12:
françois romieu4da19632011-01-03 15:07:55 +00003579 rtl8168bef_hw_phy_config(tp);
Francois Romieu236b8082008-05-30 16:11:48 +02003580 break;
3581 case RTL_GIGA_MAC_VER_17:
françois romieu4da19632011-01-03 15:07:55 +00003582 rtl8168bef_hw_phy_config(tp);
Francois Romieu236b8082008-05-30 16:11:48 +02003583 break;
Francois Romieu867763c2007-08-17 18:21:58 +02003584 case RTL_GIGA_MAC_VER_18:
françois romieu4da19632011-01-03 15:07:55 +00003585 rtl8168cp_1_hw_phy_config(tp);
Francois Romieu867763c2007-08-17 18:21:58 +02003586 break;
3587 case RTL_GIGA_MAC_VER_19:
françois romieu4da19632011-01-03 15:07:55 +00003588 rtl8168c_1_hw_phy_config(tp);
Francois Romieu867763c2007-08-17 18:21:58 +02003589 break;
Francois Romieu7da97ec2007-10-18 15:20:43 +02003590 case RTL_GIGA_MAC_VER_20:
françois romieu4da19632011-01-03 15:07:55 +00003591 rtl8168c_2_hw_phy_config(tp);
Francois Romieu7da97ec2007-10-18 15:20:43 +02003592 break;
Francois Romieu197ff762008-06-28 13:16:02 +02003593 case RTL_GIGA_MAC_VER_21:
françois romieu4da19632011-01-03 15:07:55 +00003594 rtl8168c_3_hw_phy_config(tp);
Francois Romieu197ff762008-06-28 13:16:02 +02003595 break;
Francois Romieu6fb07052008-06-29 11:54:28 +02003596 case RTL_GIGA_MAC_VER_22:
françois romieu4da19632011-01-03 15:07:55 +00003597 rtl8168c_4_hw_phy_config(tp);
Francois Romieu6fb07052008-06-29 11:54:28 +02003598 break;
Francois Romieuef3386f2008-06-29 12:24:30 +02003599 case RTL_GIGA_MAC_VER_23:
Francois Romieu7f3e3d32008-07-20 18:53:20 +02003600 case RTL_GIGA_MAC_VER_24:
françois romieu4da19632011-01-03 15:07:55 +00003601 rtl8168cp_2_hw_phy_config(tp);
Francois Romieuef3386f2008-06-29 12:24:30 +02003602 break;
Francois Romieu5b538df2008-07-20 16:22:45 +02003603 case RTL_GIGA_MAC_VER_25:
françois romieubca03d52011-01-03 15:07:31 +00003604 rtl8168d_1_hw_phy_config(tp);
françois romieudaf9df62009-10-07 12:44:20 +00003605 break;
3606 case RTL_GIGA_MAC_VER_26:
françois romieubca03d52011-01-03 15:07:31 +00003607 rtl8168d_2_hw_phy_config(tp);
françois romieudaf9df62009-10-07 12:44:20 +00003608 break;
3609 case RTL_GIGA_MAC_VER_27:
françois romieu4da19632011-01-03 15:07:55 +00003610 rtl8168d_3_hw_phy_config(tp);
Francois Romieu5b538df2008-07-20 16:22:45 +02003611 break;
françois romieue6de30d2011-01-03 15:08:37 +00003612 case RTL_GIGA_MAC_VER_28:
3613 rtl8168d_4_hw_phy_config(tp);
3614 break;
Hayes Wang5a5e4442011-02-22 17:26:21 +08003615 case RTL_GIGA_MAC_VER_29:
3616 case RTL_GIGA_MAC_VER_30:
3617 rtl8105e_hw_phy_config(tp);
3618 break;
Francois Romieucecb5fd2011-04-01 10:21:07 +02003619 case RTL_GIGA_MAC_VER_31:
3620 /* None. */
3621 break;
hayeswang01dc7fe2011-03-21 01:50:28 +00003622 case RTL_GIGA_MAC_VER_32:
hayeswang01dc7fe2011-03-21 01:50:28 +00003623 case RTL_GIGA_MAC_VER_33:
Hayes Wang70090422011-07-06 15:58:06 +08003624 rtl8168e_1_hw_phy_config(tp);
3625 break;
3626 case RTL_GIGA_MAC_VER_34:
3627 rtl8168e_2_hw_phy_config(tp);
hayeswang01dc7fe2011-03-21 01:50:28 +00003628 break;
Hayes Wangc2218922011-09-06 16:55:18 +08003629 case RTL_GIGA_MAC_VER_35:
3630 rtl8168f_1_hw_phy_config(tp);
3631 break;
3632 case RTL_GIGA_MAC_VER_36:
3633 rtl8168f_2_hw_phy_config(tp);
3634 break;
Francois Romieuef3386f2008-06-29 12:24:30 +02003635
Hayes Wang7e18dca2012-03-30 14:33:02 +08003636 case RTL_GIGA_MAC_VER_37:
3637 rtl8402_hw_phy_config(tp);
3638 break;
3639
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003640 case RTL_GIGA_MAC_VER_38:
3641 rtl8411_hw_phy_config(tp);
3642 break;
3643
Hayes Wang5598bfe2012-07-02 17:23:21 +08003644 case RTL_GIGA_MAC_VER_39:
3645 rtl8106e_hw_phy_config(tp);
3646 break;
3647
Hayes Wangc5583862012-07-02 17:23:22 +08003648 case RTL_GIGA_MAC_VER_40:
3649 rtl8168g_1_hw_phy_config(tp);
3650 break;
hayeswang57538c42013-04-01 22:23:40 +00003651 case RTL_GIGA_MAC_VER_42:
hayeswang58152cd2013-04-01 22:23:42 +00003652 case RTL_GIGA_MAC_VER_43:
hayeswang45dd95c2013-07-08 17:09:01 +08003653 case RTL_GIGA_MAC_VER_44:
hayeswang57538c42013-04-01 22:23:40 +00003654 rtl8168g_2_hw_phy_config(tp);
3655 break;
Hayes Wangc5583862012-07-02 17:23:22 +08003656
3657 case RTL_GIGA_MAC_VER_41:
Francois Romieu5615d9f2007-08-17 17:50:46 +02003658 default:
3659 break;
3660 }
3661}
3662
Francois Romieuda78dbf2012-01-26 14:18:23 +01003663static void rtl_phy_work(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003664{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003665 struct timer_list *timer = &tp->timer;
3666 void __iomem *ioaddr = tp->mmio_addr;
3667 unsigned long timeout = RTL8169_PHY_TIMEOUT;
3668
Francois Romieubcf0bf92006-07-26 23:14:13 +02003669 assert(tp->mac_version > RTL_GIGA_MAC_VER_01);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003670
françois romieu4da19632011-01-03 15:07:55 +00003671 if (tp->phy_reset_pending(tp)) {
Francois Romieu5b0384f2006-08-16 16:00:01 +02003672 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07003673 * A busy loop could burn quite a few cycles on nowadays CPU.
3674 * Let's delay the execution of the timer for a few ticks.
3675 */
3676 timeout = HZ/10;
3677 goto out_mod_timer;
3678 }
3679
3680 if (tp->link_ok(ioaddr))
Francois Romieuda78dbf2012-01-26 14:18:23 +01003681 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003682
Lekensteyn9bb8eeb2013-08-02 10:36:55 +02003683 netif_dbg(tp, link, tp->dev, "PHY reset until link up\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003684
françois romieu4da19632011-01-03 15:07:55 +00003685 tp->phy_reset_enable(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003686
3687out_mod_timer:
3688 mod_timer(timer, jiffies + timeout);
Francois Romieuda78dbf2012-01-26 14:18:23 +01003689}
3690
3691static void rtl_schedule_task(struct rtl8169_private *tp, enum rtl_flag flag)
3692{
Francois Romieuda78dbf2012-01-26 14:18:23 +01003693 if (!test_and_set_bit(flag, tp->wk.flags))
3694 schedule_work(&tp->wk.work);
Francois Romieuda78dbf2012-01-26 14:18:23 +01003695}
3696
3697static void rtl8169_phy_timer(unsigned long __opaque)
3698{
3699 struct net_device *dev = (struct net_device *)__opaque;
3700 struct rtl8169_private *tp = netdev_priv(dev);
3701
Francois Romieu98ddf982012-01-31 10:47:34 +01003702 rtl_schedule_task(tp, RTL_FLAG_TASK_PHY_PENDING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003703}
3704
Linus Torvalds1da177e2005-04-16 15:20:36 -07003705static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev,
3706 void __iomem *ioaddr)
3707{
3708 iounmap(ioaddr);
3709 pci_release_regions(pdev);
françois romieu87aeec72010-04-26 11:42:06 +00003710 pci_clear_mwi(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003711 pci_disable_device(pdev);
3712 free_netdev(dev);
3713}
3714
Francois Romieuffc46952012-07-06 14:19:23 +02003715DECLARE_RTL_COND(rtl_phy_reset_cond)
3716{
3717 return tp->phy_reset_pending(tp);
3718}
3719
Francois Romieubf793292006-11-01 00:53:05 +01003720static void rtl8169_phy_reset(struct net_device *dev,
3721 struct rtl8169_private *tp)
3722{
françois romieu4da19632011-01-03 15:07:55 +00003723 tp->phy_reset_enable(tp);
Francois Romieuffc46952012-07-06 14:19:23 +02003724 rtl_msleep_loop_wait_low(tp, &rtl_phy_reset_cond, 1, 100);
Francois Romieubf793292006-11-01 00:53:05 +01003725}
3726
David S. Miller8decf862011-09-22 03:23:13 -04003727static bool rtl_tbi_enabled(struct rtl8169_private *tp)
3728{
3729 void __iomem *ioaddr = tp->mmio_addr;
3730
3731 return (tp->mac_version == RTL_GIGA_MAC_VER_01) &&
3732 (RTL_R8(PHYstatus) & TBI_Enable);
3733}
3734
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003735static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003736{
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003737 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003738
Francois Romieu5615d9f2007-08-17 17:50:46 +02003739 rtl_hw_phy_config(dev);
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003740
Marcus Sundberg773328942008-07-10 21:28:08 +02003741 if (tp->mac_version <= RTL_GIGA_MAC_VER_06) {
3742 dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
3743 RTL_W8(0x82, 0x01);
3744 }
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003745
Francois Romieu6dccd162007-02-13 23:38:05 +01003746 pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40);
3747
3748 if (tp->mac_version <= RTL_GIGA_MAC_VER_06)
3749 pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08);
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003750
Francois Romieubcf0bf92006-07-26 23:14:13 +02003751 if (tp->mac_version == RTL_GIGA_MAC_VER_02) {
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003752 dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
3753 RTL_W8(0x82, 0x01);
3754 dprintk("Set PHY Reg 0x0bh = 0x00h\n");
françois romieu4da19632011-01-03 15:07:55 +00003755 rtl_writephy(tp, 0x0b, 0x0000); //w 0x0b 15 0 0
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003756 }
3757
Francois Romieubf793292006-11-01 00:53:05 +01003758 rtl8169_phy_reset(dev, tp);
3759
Oliver Neukum54405cd2011-01-06 21:55:13 +01003760 rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL,
Francois Romieucecb5fd2011-04-01 10:21:07 +02003761 ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
3762 ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |
3763 (tp->mii.supports_gmii ?
3764 ADVERTISED_1000baseT_Half |
3765 ADVERTISED_1000baseT_Full : 0));
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003766
David S. Miller8decf862011-09-22 03:23:13 -04003767 if (rtl_tbi_enabled(tp))
Joe Perchesbf82c182010-02-09 11:49:50 +00003768 netif_info(tp, link, dev, "TBI auto-negotiating\n");
Francois Romieu4ff96fa2006-07-26 22:05:06 +02003769}
3770
Francois Romieu773d2022007-01-31 23:47:43 +01003771static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr)
3772{
3773 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu773d2022007-01-31 23:47:43 +01003774
Francois Romieuda78dbf2012-01-26 14:18:23 +01003775 rtl_lock_work(tp);
Francois Romieu773d2022007-01-31 23:47:43 +01003776
3777 RTL_W8(Cfg9346, Cfg9346_Unlock);
françois romieu908ba2b2010-04-26 11:42:58 +00003778
françois romieu9ecb9aa2012-12-07 11:20:21 +00003779 RTL_W32(MAC4, addr[4] | addr[5] << 8);
françois romieu908ba2b2010-04-26 11:42:58 +00003780 RTL_R32(MAC4);
3781
françois romieu9ecb9aa2012-12-07 11:20:21 +00003782 RTL_W32(MAC0, addr[0] | addr[1] << 8 | addr[2] << 16 | addr[3] << 24);
françois romieu908ba2b2010-04-26 11:42:58 +00003783 RTL_R32(MAC0);
3784
françois romieu9ecb9aa2012-12-07 11:20:21 +00003785 if (tp->mac_version == RTL_GIGA_MAC_VER_34)
3786 rtl_rar_exgmac_set(tp, addr);
françois romieuc28aa382011-08-02 03:53:43 +00003787
Francois Romieu773d2022007-01-31 23:47:43 +01003788 RTL_W8(Cfg9346, Cfg9346_Lock);
3789
Francois Romieuda78dbf2012-01-26 14:18:23 +01003790 rtl_unlock_work(tp);
Francois Romieu773d2022007-01-31 23:47:43 +01003791}
3792
3793static int rtl_set_mac_address(struct net_device *dev, void *p)
3794{
3795 struct rtl8169_private *tp = netdev_priv(dev);
3796 struct sockaddr *addr = p;
3797
3798 if (!is_valid_ether_addr(addr->sa_data))
3799 return -EADDRNOTAVAIL;
3800
3801 memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
3802
3803 rtl_rar_set(tp, dev->dev_addr);
3804
3805 return 0;
3806}
3807
Francois Romieu5f787a12006-08-17 13:02:36 +02003808static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
3809{
3810 struct rtl8169_private *tp = netdev_priv(dev);
3811 struct mii_ioctl_data *data = if_mii(ifr);
3812
Francois Romieu8b4ab282008-11-19 22:05:25 -08003813 return netif_running(dev) ? tp->do_ioctl(tp, data, cmd) : -ENODEV;
3814}
Francois Romieu5f787a12006-08-17 13:02:36 +02003815
Francois Romieucecb5fd2011-04-01 10:21:07 +02003816static int rtl_xmii_ioctl(struct rtl8169_private *tp,
3817 struct mii_ioctl_data *data, int cmd)
Francois Romieu8b4ab282008-11-19 22:05:25 -08003818{
Francois Romieu5f787a12006-08-17 13:02:36 +02003819 switch (cmd) {
3820 case SIOCGMIIPHY:
3821 data->phy_id = 32; /* Internal PHY */
3822 return 0;
3823
3824 case SIOCGMIIREG:
françois romieu4da19632011-01-03 15:07:55 +00003825 data->val_out = rtl_readphy(tp, data->reg_num & 0x1f);
Francois Romieu5f787a12006-08-17 13:02:36 +02003826 return 0;
3827
3828 case SIOCSMIIREG:
françois romieu4da19632011-01-03 15:07:55 +00003829 rtl_writephy(tp, data->reg_num & 0x1f, data->val_in);
Francois Romieu5f787a12006-08-17 13:02:36 +02003830 return 0;
3831 }
3832 return -EOPNOTSUPP;
3833}
3834
Francois Romieu8b4ab282008-11-19 22:05:25 -08003835static int rtl_tbi_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd)
3836{
3837 return -EOPNOTSUPP;
3838}
3839
Francois Romieufbac58f2007-10-04 22:51:38 +02003840static void rtl_disable_msi(struct pci_dev *pdev, struct rtl8169_private *tp)
3841{
3842 if (tp->features & RTL_FEATURE_MSI) {
3843 pci_disable_msi(pdev);
3844 tp->features &= ~RTL_FEATURE_MSI;
3845 }
3846}
3847
Bill Pembertonbaf63292012-12-03 09:23:28 -05003848static void rtl_init_mdio_ops(struct rtl8169_private *tp)
françois romieuc0e45c12011-01-03 15:08:04 +00003849{
3850 struct mdio_ops *ops = &tp->mdio_ops;
3851
3852 switch (tp->mac_version) {
3853 case RTL_GIGA_MAC_VER_27:
3854 ops->write = r8168dp_1_mdio_write;
3855 ops->read = r8168dp_1_mdio_read;
3856 break;
françois romieue6de30d2011-01-03 15:08:37 +00003857 case RTL_GIGA_MAC_VER_28:
hayeswang4804b3b2011-03-21 01:50:29 +00003858 case RTL_GIGA_MAC_VER_31:
françois romieue6de30d2011-01-03 15:08:37 +00003859 ops->write = r8168dp_2_mdio_write;
3860 ops->read = r8168dp_2_mdio_read;
3861 break;
Hayes Wangc5583862012-07-02 17:23:22 +08003862 case RTL_GIGA_MAC_VER_40:
3863 case RTL_GIGA_MAC_VER_41:
hayeswang57538c42013-04-01 22:23:40 +00003864 case RTL_GIGA_MAC_VER_42:
hayeswang58152cd2013-04-01 22:23:42 +00003865 case RTL_GIGA_MAC_VER_43:
hayeswang45dd95c2013-07-08 17:09:01 +08003866 case RTL_GIGA_MAC_VER_44:
Hayes Wangc5583862012-07-02 17:23:22 +08003867 ops->write = r8168g_mdio_write;
3868 ops->read = r8168g_mdio_read;
3869 break;
françois romieuc0e45c12011-01-03 15:08:04 +00003870 default:
3871 ops->write = r8169_mdio_write;
3872 ops->read = r8169_mdio_read;
3873 break;
3874 }
3875}
3876
hayeswange2409d82013-03-31 17:02:04 +00003877static void rtl_speed_down(struct rtl8169_private *tp)
3878{
3879 u32 adv;
3880 int lpa;
3881
3882 rtl_writephy(tp, 0x1f, 0x0000);
3883 lpa = rtl_readphy(tp, MII_LPA);
3884
3885 if (lpa & (LPA_10HALF | LPA_10FULL))
3886 adv = ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full;
3887 else if (lpa & (LPA_100HALF | LPA_100FULL))
3888 adv = ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
3889 ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full;
3890 else
3891 adv = ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
3892 ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |
3893 (tp->mii.supports_gmii ?
3894 ADVERTISED_1000baseT_Half |
3895 ADVERTISED_1000baseT_Full : 0);
3896
3897 rtl8169_set_speed(tp->dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL,
3898 adv);
3899}
3900
David S. Miller1805b2f2011-10-24 18:18:09 -04003901static void rtl_wol_suspend_quirk(struct rtl8169_private *tp)
3902{
3903 void __iomem *ioaddr = tp->mmio_addr;
3904
3905 switch (tp->mac_version) {
Cyril Bruleboisb00e69d2012-10-31 14:00:46 +00003906 case RTL_GIGA_MAC_VER_25:
3907 case RTL_GIGA_MAC_VER_26:
David S. Miller1805b2f2011-10-24 18:18:09 -04003908 case RTL_GIGA_MAC_VER_29:
3909 case RTL_GIGA_MAC_VER_30:
3910 case RTL_GIGA_MAC_VER_32:
3911 case RTL_GIGA_MAC_VER_33:
3912 case RTL_GIGA_MAC_VER_34:
Hayes Wang7e18dca2012-03-30 14:33:02 +08003913 case RTL_GIGA_MAC_VER_37:
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08003914 case RTL_GIGA_MAC_VER_38:
Hayes Wang5598bfe2012-07-02 17:23:21 +08003915 case RTL_GIGA_MAC_VER_39:
Hayes Wangc5583862012-07-02 17:23:22 +08003916 case RTL_GIGA_MAC_VER_40:
3917 case RTL_GIGA_MAC_VER_41:
hayeswang57538c42013-04-01 22:23:40 +00003918 case RTL_GIGA_MAC_VER_42:
hayeswang58152cd2013-04-01 22:23:42 +00003919 case RTL_GIGA_MAC_VER_43:
hayeswang45dd95c2013-07-08 17:09:01 +08003920 case RTL_GIGA_MAC_VER_44:
David S. Miller1805b2f2011-10-24 18:18:09 -04003921 RTL_W32(RxConfig, RTL_R32(RxConfig) |
3922 AcceptBroadcast | AcceptMulticast | AcceptMyPhys);
3923 break;
3924 default:
3925 break;
3926 }
3927}
3928
3929static bool rtl_wol_pll_power_down(struct rtl8169_private *tp)
3930{
3931 if (!(__rtl8169_get_wol(tp) & WAKE_ANY))
3932 return false;
3933
hayeswange2409d82013-03-31 17:02:04 +00003934 rtl_speed_down(tp);
David S. Miller1805b2f2011-10-24 18:18:09 -04003935 rtl_wol_suspend_quirk(tp);
3936
3937 return true;
3938}
3939
françois romieu065c27c2011-01-03 15:08:12 +00003940static void r810x_phy_power_down(struct rtl8169_private *tp)
3941{
3942 rtl_writephy(tp, 0x1f, 0x0000);
3943 rtl_writephy(tp, MII_BMCR, BMCR_PDOWN);
3944}
3945
3946static void r810x_phy_power_up(struct rtl8169_private *tp)
3947{
3948 rtl_writephy(tp, 0x1f, 0x0000);
3949 rtl_writephy(tp, MII_BMCR, BMCR_ANENABLE);
3950}
3951
3952static void r810x_pll_power_down(struct rtl8169_private *tp)
3953{
Hayes Wang00042992012-03-30 14:33:00 +08003954 void __iomem *ioaddr = tp->mmio_addr;
3955
David S. Miller1805b2f2011-10-24 18:18:09 -04003956 if (rtl_wol_pll_power_down(tp))
françois romieu065c27c2011-01-03 15:08:12 +00003957 return;
françois romieu065c27c2011-01-03 15:08:12 +00003958
3959 r810x_phy_power_down(tp);
Hayes Wang00042992012-03-30 14:33:00 +08003960
3961 switch (tp->mac_version) {
3962 case RTL_GIGA_MAC_VER_07:
3963 case RTL_GIGA_MAC_VER_08:
3964 case RTL_GIGA_MAC_VER_09:
3965 case RTL_GIGA_MAC_VER_10:
3966 case RTL_GIGA_MAC_VER_13:
3967 case RTL_GIGA_MAC_VER_16:
3968 break;
3969 default:
3970 RTL_W8(PMCH, RTL_R8(PMCH) & ~0x80);
3971 break;
3972 }
françois romieu065c27c2011-01-03 15:08:12 +00003973}
3974
3975static void r810x_pll_power_up(struct rtl8169_private *tp)
3976{
Hayes Wang00042992012-03-30 14:33:00 +08003977 void __iomem *ioaddr = tp->mmio_addr;
3978
françois romieu065c27c2011-01-03 15:08:12 +00003979 r810x_phy_power_up(tp);
Hayes Wang00042992012-03-30 14:33:00 +08003980
3981 switch (tp->mac_version) {
3982 case RTL_GIGA_MAC_VER_07:
3983 case RTL_GIGA_MAC_VER_08:
3984 case RTL_GIGA_MAC_VER_09:
3985 case RTL_GIGA_MAC_VER_10:
3986 case RTL_GIGA_MAC_VER_13:
3987 case RTL_GIGA_MAC_VER_16:
3988 break;
3989 default:
3990 RTL_W8(PMCH, RTL_R8(PMCH) | 0x80);
3991 break;
3992 }
françois romieu065c27c2011-01-03 15:08:12 +00003993}
3994
3995static void r8168_phy_power_up(struct rtl8169_private *tp)
3996{
3997 rtl_writephy(tp, 0x1f, 0x0000);
hayeswang01dc7fe2011-03-21 01:50:28 +00003998 switch (tp->mac_version) {
3999 case RTL_GIGA_MAC_VER_11:
4000 case RTL_GIGA_MAC_VER_12:
4001 case RTL_GIGA_MAC_VER_17:
4002 case RTL_GIGA_MAC_VER_18:
4003 case RTL_GIGA_MAC_VER_19:
4004 case RTL_GIGA_MAC_VER_20:
4005 case RTL_GIGA_MAC_VER_21:
4006 case RTL_GIGA_MAC_VER_22:
4007 case RTL_GIGA_MAC_VER_23:
4008 case RTL_GIGA_MAC_VER_24:
4009 case RTL_GIGA_MAC_VER_25:
4010 case RTL_GIGA_MAC_VER_26:
4011 case RTL_GIGA_MAC_VER_27:
4012 case RTL_GIGA_MAC_VER_28:
4013 case RTL_GIGA_MAC_VER_31:
4014 rtl_writephy(tp, 0x0e, 0x0000);
4015 break;
4016 default:
4017 break;
4018 }
françois romieu065c27c2011-01-03 15:08:12 +00004019 rtl_writephy(tp, MII_BMCR, BMCR_ANENABLE);
4020}
4021
4022static void r8168_phy_power_down(struct rtl8169_private *tp)
4023{
4024 rtl_writephy(tp, 0x1f, 0x0000);
hayeswang01dc7fe2011-03-21 01:50:28 +00004025 switch (tp->mac_version) {
4026 case RTL_GIGA_MAC_VER_32:
4027 case RTL_GIGA_MAC_VER_33:
hayeswangbeb330a2013-04-01 22:23:39 +00004028 case RTL_GIGA_MAC_VER_40:
4029 case RTL_GIGA_MAC_VER_41:
hayeswang01dc7fe2011-03-21 01:50:28 +00004030 rtl_writephy(tp, MII_BMCR, BMCR_ANENABLE | BMCR_PDOWN);
4031 break;
4032
4033 case RTL_GIGA_MAC_VER_11:
4034 case RTL_GIGA_MAC_VER_12:
4035 case RTL_GIGA_MAC_VER_17:
4036 case RTL_GIGA_MAC_VER_18:
4037 case RTL_GIGA_MAC_VER_19:
4038 case RTL_GIGA_MAC_VER_20:
4039 case RTL_GIGA_MAC_VER_21:
4040 case RTL_GIGA_MAC_VER_22:
4041 case RTL_GIGA_MAC_VER_23:
4042 case RTL_GIGA_MAC_VER_24:
4043 case RTL_GIGA_MAC_VER_25:
4044 case RTL_GIGA_MAC_VER_26:
4045 case RTL_GIGA_MAC_VER_27:
4046 case RTL_GIGA_MAC_VER_28:
4047 case RTL_GIGA_MAC_VER_31:
4048 rtl_writephy(tp, 0x0e, 0x0200);
4049 default:
4050 rtl_writephy(tp, MII_BMCR, BMCR_PDOWN);
4051 break;
4052 }
françois romieu065c27c2011-01-03 15:08:12 +00004053}
4054
4055static void r8168_pll_power_down(struct rtl8169_private *tp)
4056{
4057 void __iomem *ioaddr = tp->mmio_addr;
4058
Francois Romieucecb5fd2011-04-01 10:21:07 +02004059 if ((tp->mac_version == RTL_GIGA_MAC_VER_27 ||
4060 tp->mac_version == RTL_GIGA_MAC_VER_28 ||
4061 tp->mac_version == RTL_GIGA_MAC_VER_31) &&
hayeswang4804b3b2011-03-21 01:50:29 +00004062 r8168dp_check_dash(tp)) {
françois romieu065c27c2011-01-03 15:08:12 +00004063 return;
Hayes Wang5d2e1952011-02-22 17:26:22 +08004064 }
françois romieu065c27c2011-01-03 15:08:12 +00004065
Francois Romieucecb5fd2011-04-01 10:21:07 +02004066 if ((tp->mac_version == RTL_GIGA_MAC_VER_23 ||
4067 tp->mac_version == RTL_GIGA_MAC_VER_24) &&
françois romieu065c27c2011-01-03 15:08:12 +00004068 (RTL_R16(CPlusCmd) & ASF)) {
4069 return;
4070 }
4071
hayeswang01dc7fe2011-03-21 01:50:28 +00004072 if (tp->mac_version == RTL_GIGA_MAC_VER_32 ||
4073 tp->mac_version == RTL_GIGA_MAC_VER_33)
Francois Romieufdf6fc02012-07-06 22:40:38 +02004074 rtl_ephy_write(tp, 0x19, 0xff64);
hayeswang01dc7fe2011-03-21 01:50:28 +00004075
David S. Miller1805b2f2011-10-24 18:18:09 -04004076 if (rtl_wol_pll_power_down(tp))
françois romieu065c27c2011-01-03 15:08:12 +00004077 return;
françois romieu065c27c2011-01-03 15:08:12 +00004078
4079 r8168_phy_power_down(tp);
4080
4081 switch (tp->mac_version) {
4082 case RTL_GIGA_MAC_VER_25:
4083 case RTL_GIGA_MAC_VER_26:
Hayes Wang5d2e1952011-02-22 17:26:22 +08004084 case RTL_GIGA_MAC_VER_27:
4085 case RTL_GIGA_MAC_VER_28:
hayeswang4804b3b2011-03-21 01:50:29 +00004086 case RTL_GIGA_MAC_VER_31:
hayeswang01dc7fe2011-03-21 01:50:28 +00004087 case RTL_GIGA_MAC_VER_32:
4088 case RTL_GIGA_MAC_VER_33:
françois romieu065c27c2011-01-03 15:08:12 +00004089 RTL_W8(PMCH, RTL_R8(PMCH) & ~0x80);
4090 break;
hayeswangbeb330a2013-04-01 22:23:39 +00004091 case RTL_GIGA_MAC_VER_40:
4092 case RTL_GIGA_MAC_VER_41:
4093 rtl_w1w0_eri(tp, 0x1a8, ERIAR_MASK_1111, 0x00000000,
4094 0xfc000000, ERIAR_EXGMAC);
4095 break;
françois romieu065c27c2011-01-03 15:08:12 +00004096 }
4097}
4098
4099static void r8168_pll_power_up(struct rtl8169_private *tp)
4100{
4101 void __iomem *ioaddr = tp->mmio_addr;
4102
françois romieu065c27c2011-01-03 15:08:12 +00004103 switch (tp->mac_version) {
4104 case RTL_GIGA_MAC_VER_25:
4105 case RTL_GIGA_MAC_VER_26:
Hayes Wang5d2e1952011-02-22 17:26:22 +08004106 case RTL_GIGA_MAC_VER_27:
4107 case RTL_GIGA_MAC_VER_28:
hayeswang4804b3b2011-03-21 01:50:29 +00004108 case RTL_GIGA_MAC_VER_31:
hayeswang01dc7fe2011-03-21 01:50:28 +00004109 case RTL_GIGA_MAC_VER_32:
4110 case RTL_GIGA_MAC_VER_33:
françois romieu065c27c2011-01-03 15:08:12 +00004111 RTL_W8(PMCH, RTL_R8(PMCH) | 0x80);
4112 break;
hayeswangbeb330a2013-04-01 22:23:39 +00004113 case RTL_GIGA_MAC_VER_40:
4114 case RTL_GIGA_MAC_VER_41:
4115 rtl_w1w0_eri(tp, 0x1a8, ERIAR_MASK_1111, 0xfc000000,
4116 0x00000000, ERIAR_EXGMAC);
4117 break;
françois romieu065c27c2011-01-03 15:08:12 +00004118 }
4119
4120 r8168_phy_power_up(tp);
4121}
4122
Francois Romieud58d46b2011-05-03 16:38:29 +02004123static void rtl_generic_op(struct rtl8169_private *tp,
4124 void (*op)(struct rtl8169_private *))
françois romieu065c27c2011-01-03 15:08:12 +00004125{
4126 if (op)
4127 op(tp);
4128}
4129
4130static void rtl_pll_power_down(struct rtl8169_private *tp)
4131{
Francois Romieud58d46b2011-05-03 16:38:29 +02004132 rtl_generic_op(tp, tp->pll_power_ops.down);
françois romieu065c27c2011-01-03 15:08:12 +00004133}
4134
4135static void rtl_pll_power_up(struct rtl8169_private *tp)
4136{
Francois Romieud58d46b2011-05-03 16:38:29 +02004137 rtl_generic_op(tp, tp->pll_power_ops.up);
françois romieu065c27c2011-01-03 15:08:12 +00004138}
4139
Bill Pembertonbaf63292012-12-03 09:23:28 -05004140static void rtl_init_pll_power_ops(struct rtl8169_private *tp)
françois romieu065c27c2011-01-03 15:08:12 +00004141{
4142 struct pll_power_ops *ops = &tp->pll_power_ops;
4143
4144 switch (tp->mac_version) {
4145 case RTL_GIGA_MAC_VER_07:
4146 case RTL_GIGA_MAC_VER_08:
4147 case RTL_GIGA_MAC_VER_09:
4148 case RTL_GIGA_MAC_VER_10:
4149 case RTL_GIGA_MAC_VER_16:
Hayes Wang5a5e4442011-02-22 17:26:21 +08004150 case RTL_GIGA_MAC_VER_29:
4151 case RTL_GIGA_MAC_VER_30:
Hayes Wang7e18dca2012-03-30 14:33:02 +08004152 case RTL_GIGA_MAC_VER_37:
Hayes Wang5598bfe2012-07-02 17:23:21 +08004153 case RTL_GIGA_MAC_VER_39:
hayeswang58152cd2013-04-01 22:23:42 +00004154 case RTL_GIGA_MAC_VER_43:
françois romieu065c27c2011-01-03 15:08:12 +00004155 ops->down = r810x_pll_power_down;
4156 ops->up = r810x_pll_power_up;
4157 break;
4158
4159 case RTL_GIGA_MAC_VER_11:
4160 case RTL_GIGA_MAC_VER_12:
4161 case RTL_GIGA_MAC_VER_17:
4162 case RTL_GIGA_MAC_VER_18:
4163 case RTL_GIGA_MAC_VER_19:
4164 case RTL_GIGA_MAC_VER_20:
4165 case RTL_GIGA_MAC_VER_21:
4166 case RTL_GIGA_MAC_VER_22:
4167 case RTL_GIGA_MAC_VER_23:
4168 case RTL_GIGA_MAC_VER_24:
4169 case RTL_GIGA_MAC_VER_25:
4170 case RTL_GIGA_MAC_VER_26:
4171 case RTL_GIGA_MAC_VER_27:
françois romieue6de30d2011-01-03 15:08:37 +00004172 case RTL_GIGA_MAC_VER_28:
hayeswang4804b3b2011-03-21 01:50:29 +00004173 case RTL_GIGA_MAC_VER_31:
hayeswang01dc7fe2011-03-21 01:50:28 +00004174 case RTL_GIGA_MAC_VER_32:
4175 case RTL_GIGA_MAC_VER_33:
Hayes Wang70090422011-07-06 15:58:06 +08004176 case RTL_GIGA_MAC_VER_34:
Hayes Wangc2218922011-09-06 16:55:18 +08004177 case RTL_GIGA_MAC_VER_35:
4178 case RTL_GIGA_MAC_VER_36:
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08004179 case RTL_GIGA_MAC_VER_38:
Hayes Wangc5583862012-07-02 17:23:22 +08004180 case RTL_GIGA_MAC_VER_40:
4181 case RTL_GIGA_MAC_VER_41:
hayeswang57538c42013-04-01 22:23:40 +00004182 case RTL_GIGA_MAC_VER_42:
hayeswang45dd95c2013-07-08 17:09:01 +08004183 case RTL_GIGA_MAC_VER_44:
françois romieu065c27c2011-01-03 15:08:12 +00004184 ops->down = r8168_pll_power_down;
4185 ops->up = r8168_pll_power_up;
4186 break;
4187
4188 default:
4189 ops->down = NULL;
4190 ops->up = NULL;
4191 break;
4192 }
4193}
4194
Hayes Wange542a222011-07-06 15:58:04 +08004195static void rtl_init_rxcfg(struct rtl8169_private *tp)
4196{
4197 void __iomem *ioaddr = tp->mmio_addr;
4198
4199 switch (tp->mac_version) {
4200 case RTL_GIGA_MAC_VER_01:
4201 case RTL_GIGA_MAC_VER_02:
4202 case RTL_GIGA_MAC_VER_03:
4203 case RTL_GIGA_MAC_VER_04:
4204 case RTL_GIGA_MAC_VER_05:
4205 case RTL_GIGA_MAC_VER_06:
4206 case RTL_GIGA_MAC_VER_10:
4207 case RTL_GIGA_MAC_VER_11:
4208 case RTL_GIGA_MAC_VER_12:
4209 case RTL_GIGA_MAC_VER_13:
4210 case RTL_GIGA_MAC_VER_14:
4211 case RTL_GIGA_MAC_VER_15:
4212 case RTL_GIGA_MAC_VER_16:
4213 case RTL_GIGA_MAC_VER_17:
4214 RTL_W32(RxConfig, RX_FIFO_THRESH | RX_DMA_BURST);
4215 break;
4216 case RTL_GIGA_MAC_VER_18:
4217 case RTL_GIGA_MAC_VER_19:
4218 case RTL_GIGA_MAC_VER_20:
4219 case RTL_GIGA_MAC_VER_21:
4220 case RTL_GIGA_MAC_VER_22:
4221 case RTL_GIGA_MAC_VER_23:
4222 case RTL_GIGA_MAC_VER_24:
françois romieueb2dc352012-06-20 12:09:18 +00004223 case RTL_GIGA_MAC_VER_34:
françois romieu3ced8c92013-09-08 01:15:35 +02004224 case RTL_GIGA_MAC_VER_35:
Hayes Wange542a222011-07-06 15:58:04 +08004225 RTL_W32(RxConfig, RX128_INT_EN | RX_MULTI_EN | RX_DMA_BURST);
4226 break;
hayeswangbeb330a2013-04-01 22:23:39 +00004227 case RTL_GIGA_MAC_VER_40:
4228 case RTL_GIGA_MAC_VER_41:
hayeswang57538c42013-04-01 22:23:40 +00004229 case RTL_GIGA_MAC_VER_42:
hayeswang58152cd2013-04-01 22:23:42 +00004230 case RTL_GIGA_MAC_VER_43:
hayeswang45dd95c2013-07-08 17:09:01 +08004231 case RTL_GIGA_MAC_VER_44:
hayeswangbeb330a2013-04-01 22:23:39 +00004232 RTL_W32(RxConfig, RX128_INT_EN | RX_DMA_BURST | RX_EARLY_OFF);
4233 break;
Hayes Wange542a222011-07-06 15:58:04 +08004234 default:
4235 RTL_W32(RxConfig, RX128_INT_EN | RX_DMA_BURST);
4236 break;
4237 }
4238}
4239
Hayes Wang92fc43b2011-07-06 15:58:03 +08004240static void rtl8169_init_ring_indexes(struct rtl8169_private *tp)
4241{
Timo Teräs9fba0812013-01-15 21:01:24 +00004242 tp->dirty_tx = tp->cur_tx = tp->cur_rx = 0;
Hayes Wang92fc43b2011-07-06 15:58:03 +08004243}
4244
Francois Romieud58d46b2011-05-03 16:38:29 +02004245static void rtl_hw_jumbo_enable(struct rtl8169_private *tp)
4246{
françois romieu9c5028e2012-03-02 04:43:14 +00004247 void __iomem *ioaddr = tp->mmio_addr;
4248
4249 RTL_W8(Cfg9346, Cfg9346_Unlock);
Francois Romieud58d46b2011-05-03 16:38:29 +02004250 rtl_generic_op(tp, tp->jumbo_ops.enable);
françois romieu9c5028e2012-03-02 04:43:14 +00004251 RTL_W8(Cfg9346, Cfg9346_Lock);
Francois Romieud58d46b2011-05-03 16:38:29 +02004252}
4253
4254static void rtl_hw_jumbo_disable(struct rtl8169_private *tp)
4255{
françois romieu9c5028e2012-03-02 04:43:14 +00004256 void __iomem *ioaddr = tp->mmio_addr;
4257
4258 RTL_W8(Cfg9346, Cfg9346_Unlock);
Francois Romieud58d46b2011-05-03 16:38:29 +02004259 rtl_generic_op(tp, tp->jumbo_ops.disable);
françois romieu9c5028e2012-03-02 04:43:14 +00004260 RTL_W8(Cfg9346, Cfg9346_Lock);
Francois Romieud58d46b2011-05-03 16:38:29 +02004261}
4262
4263static void r8168c_hw_jumbo_enable(struct rtl8169_private *tp)
4264{
4265 void __iomem *ioaddr = tp->mmio_addr;
4266
4267 RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0);
4268 RTL_W8(Config4, RTL_R8(Config4) | Jumbo_En1);
4269 rtl_tx_performance_tweak(tp->pci_dev, 0x2 << MAX_READ_REQUEST_SHIFT);
4270}
4271
4272static void r8168c_hw_jumbo_disable(struct rtl8169_private *tp)
4273{
4274 void __iomem *ioaddr = tp->mmio_addr;
4275
4276 RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0);
4277 RTL_W8(Config4, RTL_R8(Config4) & ~Jumbo_En1);
4278 rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT);
4279}
4280
4281static void r8168dp_hw_jumbo_enable(struct rtl8169_private *tp)
4282{
4283 void __iomem *ioaddr = tp->mmio_addr;
4284
4285 RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0);
4286}
4287
4288static void r8168dp_hw_jumbo_disable(struct rtl8169_private *tp)
4289{
4290 void __iomem *ioaddr = tp->mmio_addr;
4291
4292 RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0);
4293}
4294
4295static void r8168e_hw_jumbo_enable(struct rtl8169_private *tp)
4296{
4297 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieud58d46b2011-05-03 16:38:29 +02004298
4299 RTL_W8(MaxTxPacketSize, 0x3f);
4300 RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0);
4301 RTL_W8(Config4, RTL_R8(Config4) | 0x01);
Francois Romieu4512ff92011-12-22 18:59:37 +01004302 rtl_tx_performance_tweak(tp->pci_dev, 0x2 << MAX_READ_REQUEST_SHIFT);
Francois Romieud58d46b2011-05-03 16:38:29 +02004303}
4304
4305static void r8168e_hw_jumbo_disable(struct rtl8169_private *tp)
4306{
4307 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieud58d46b2011-05-03 16:38:29 +02004308
4309 RTL_W8(MaxTxPacketSize, 0x0c);
4310 RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0);
4311 RTL_W8(Config4, RTL_R8(Config4) & ~0x01);
Francois Romieu4512ff92011-12-22 18:59:37 +01004312 rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT);
Francois Romieud58d46b2011-05-03 16:38:29 +02004313}
4314
4315static void r8168b_0_hw_jumbo_enable(struct rtl8169_private *tp)
4316{
4317 rtl_tx_performance_tweak(tp->pci_dev,
4318 (0x2 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN);
4319}
4320
4321static void r8168b_0_hw_jumbo_disable(struct rtl8169_private *tp)
4322{
4323 rtl_tx_performance_tweak(tp->pci_dev,
4324 (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN);
4325}
4326
4327static void r8168b_1_hw_jumbo_enable(struct rtl8169_private *tp)
4328{
4329 void __iomem *ioaddr = tp->mmio_addr;
4330
4331 r8168b_0_hw_jumbo_enable(tp);
4332
4333 RTL_W8(Config4, RTL_R8(Config4) | (1 << 0));
4334}
4335
4336static void r8168b_1_hw_jumbo_disable(struct rtl8169_private *tp)
4337{
4338 void __iomem *ioaddr = tp->mmio_addr;
4339
4340 r8168b_0_hw_jumbo_disable(tp);
4341
4342 RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0));
4343}
4344
Bill Pembertonbaf63292012-12-03 09:23:28 -05004345static void rtl_init_jumbo_ops(struct rtl8169_private *tp)
Francois Romieud58d46b2011-05-03 16:38:29 +02004346{
4347 struct jumbo_ops *ops = &tp->jumbo_ops;
4348
4349 switch (tp->mac_version) {
4350 case RTL_GIGA_MAC_VER_11:
4351 ops->disable = r8168b_0_hw_jumbo_disable;
4352 ops->enable = r8168b_0_hw_jumbo_enable;
4353 break;
4354 case RTL_GIGA_MAC_VER_12:
4355 case RTL_GIGA_MAC_VER_17:
4356 ops->disable = r8168b_1_hw_jumbo_disable;
4357 ops->enable = r8168b_1_hw_jumbo_enable;
4358 break;
4359 case RTL_GIGA_MAC_VER_18: /* Wild guess. Needs info from Realtek. */
4360 case RTL_GIGA_MAC_VER_19:
4361 case RTL_GIGA_MAC_VER_20:
4362 case RTL_GIGA_MAC_VER_21: /* Wild guess. Needs info from Realtek. */
4363 case RTL_GIGA_MAC_VER_22:
4364 case RTL_GIGA_MAC_VER_23:
4365 case RTL_GIGA_MAC_VER_24:
4366 case RTL_GIGA_MAC_VER_25:
4367 case RTL_GIGA_MAC_VER_26:
4368 ops->disable = r8168c_hw_jumbo_disable;
4369 ops->enable = r8168c_hw_jumbo_enable;
4370 break;
4371 case RTL_GIGA_MAC_VER_27:
4372 case RTL_GIGA_MAC_VER_28:
4373 ops->disable = r8168dp_hw_jumbo_disable;
4374 ops->enable = r8168dp_hw_jumbo_enable;
4375 break;
4376 case RTL_GIGA_MAC_VER_31: /* Wild guess. Needs info from Realtek. */
4377 case RTL_GIGA_MAC_VER_32:
4378 case RTL_GIGA_MAC_VER_33:
4379 case RTL_GIGA_MAC_VER_34:
4380 ops->disable = r8168e_hw_jumbo_disable;
4381 ops->enable = r8168e_hw_jumbo_enable;
4382 break;
4383
4384 /*
4385 * No action needed for jumbo frames with 8169.
4386 * No jumbo for 810x at all.
4387 */
Hayes Wangc5583862012-07-02 17:23:22 +08004388 case RTL_GIGA_MAC_VER_40:
4389 case RTL_GIGA_MAC_VER_41:
hayeswang57538c42013-04-01 22:23:40 +00004390 case RTL_GIGA_MAC_VER_42:
hayeswang58152cd2013-04-01 22:23:42 +00004391 case RTL_GIGA_MAC_VER_43:
hayeswang45dd95c2013-07-08 17:09:01 +08004392 case RTL_GIGA_MAC_VER_44:
Francois Romieud58d46b2011-05-03 16:38:29 +02004393 default:
4394 ops->disable = NULL;
4395 ops->enable = NULL;
4396 break;
4397 }
4398}
4399
Francois Romieuffc46952012-07-06 14:19:23 +02004400DECLARE_RTL_COND(rtl_chipcmd_cond)
4401{
4402 void __iomem *ioaddr = tp->mmio_addr;
4403
4404 return RTL_R8(ChipCmd) & CmdReset;
4405}
4406
Francois Romieu6f43adc2011-04-29 15:05:51 +02004407static void rtl_hw_reset(struct rtl8169_private *tp)
4408{
4409 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu6f43adc2011-04-29 15:05:51 +02004410
Francois Romieu6f43adc2011-04-29 15:05:51 +02004411 RTL_W8(ChipCmd, CmdReset);
4412
Francois Romieuffc46952012-07-06 14:19:23 +02004413 rtl_udelay_loop_wait_low(tp, &rtl_chipcmd_cond, 100, 100);
Francois Romieu6f43adc2011-04-29 15:05:51 +02004414}
4415
Francois Romieub6ffd972011-06-17 17:00:05 +02004416static void rtl_request_uncached_firmware(struct rtl8169_private *tp)
4417{
4418 struct rtl_fw *rtl_fw;
4419 const char *name;
4420 int rc = -ENOMEM;
4421
4422 name = rtl_lookup_firmware_name(tp);
4423 if (!name)
4424 goto out_no_firmware;
4425
4426 rtl_fw = kzalloc(sizeof(*rtl_fw), GFP_KERNEL);
4427 if (!rtl_fw)
4428 goto err_warn;
4429
4430 rc = request_firmware(&rtl_fw->fw, name, &tp->pci_dev->dev);
4431 if (rc < 0)
4432 goto err_free;
4433
Francois Romieufd112f22011-06-18 00:10:29 +02004434 rc = rtl_check_firmware(tp, rtl_fw);
4435 if (rc < 0)
4436 goto err_release_firmware;
4437
Francois Romieub6ffd972011-06-17 17:00:05 +02004438 tp->rtl_fw = rtl_fw;
4439out:
4440 return;
4441
Francois Romieufd112f22011-06-18 00:10:29 +02004442err_release_firmware:
4443 release_firmware(rtl_fw->fw);
Francois Romieub6ffd972011-06-17 17:00:05 +02004444err_free:
4445 kfree(rtl_fw);
4446err_warn:
4447 netif_warn(tp, ifup, tp->dev, "unable to load firmware patch %s (%d)\n",
4448 name, rc);
4449out_no_firmware:
4450 tp->rtl_fw = NULL;
4451 goto out;
4452}
4453
François Romieu953a12c2011-04-24 17:38:48 +02004454static void rtl_request_firmware(struct rtl8169_private *tp)
4455{
Francois Romieub6ffd972011-06-17 17:00:05 +02004456 if (IS_ERR(tp->rtl_fw))
4457 rtl_request_uncached_firmware(tp);
François Romieu953a12c2011-04-24 17:38:48 +02004458}
4459
Hayes Wang92fc43b2011-07-06 15:58:03 +08004460static void rtl_rx_close(struct rtl8169_private *tp)
4461{
4462 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang92fc43b2011-07-06 15:58:03 +08004463
Francois Romieu1687b562011-07-19 17:21:29 +02004464 RTL_W32(RxConfig, RTL_R32(RxConfig) & ~RX_CONFIG_ACCEPT_MASK);
Hayes Wang92fc43b2011-07-06 15:58:03 +08004465}
4466
Francois Romieuffc46952012-07-06 14:19:23 +02004467DECLARE_RTL_COND(rtl_npq_cond)
4468{
4469 void __iomem *ioaddr = tp->mmio_addr;
4470
4471 return RTL_R8(TxPoll) & NPQ;
4472}
4473
4474DECLARE_RTL_COND(rtl_txcfg_empty_cond)
4475{
4476 void __iomem *ioaddr = tp->mmio_addr;
4477
4478 return RTL_R32(TxConfig) & TXCFG_EMPTY;
4479}
4480
françois romieue6de30d2011-01-03 15:08:37 +00004481static void rtl8169_hw_reset(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004482{
françois romieue6de30d2011-01-03 15:08:37 +00004483 void __iomem *ioaddr = tp->mmio_addr;
4484
Linus Torvalds1da177e2005-04-16 15:20:36 -07004485 /* Disable interrupts */
françois romieu811fd302011-12-04 20:30:45 +00004486 rtl8169_irq_mask_and_ack(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004487
Hayes Wang92fc43b2011-07-06 15:58:03 +08004488 rtl_rx_close(tp);
4489
Hayes Wang5d2e1952011-02-22 17:26:22 +08004490 if (tp->mac_version == RTL_GIGA_MAC_VER_27 ||
hayeswang4804b3b2011-03-21 01:50:29 +00004491 tp->mac_version == RTL_GIGA_MAC_VER_28 ||
4492 tp->mac_version == RTL_GIGA_MAC_VER_31) {
Francois Romieuffc46952012-07-06 14:19:23 +02004493 rtl_udelay_loop_wait_low(tp, &rtl_npq_cond, 20, 42*42);
Hayes Wangc2218922011-09-06 16:55:18 +08004494 } else if (tp->mac_version == RTL_GIGA_MAC_VER_34 ||
4495 tp->mac_version == RTL_GIGA_MAC_VER_35 ||
Hayes Wang7e18dca2012-03-30 14:33:02 +08004496 tp->mac_version == RTL_GIGA_MAC_VER_36 ||
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08004497 tp->mac_version == RTL_GIGA_MAC_VER_37 ||
Hayes Wangc5583862012-07-02 17:23:22 +08004498 tp->mac_version == RTL_GIGA_MAC_VER_40 ||
4499 tp->mac_version == RTL_GIGA_MAC_VER_41 ||
hayeswang57538c42013-04-01 22:23:40 +00004500 tp->mac_version == RTL_GIGA_MAC_VER_42 ||
hayeswang58152cd2013-04-01 22:23:42 +00004501 tp->mac_version == RTL_GIGA_MAC_VER_43 ||
hayeswang45dd95c2013-07-08 17:09:01 +08004502 tp->mac_version == RTL_GIGA_MAC_VER_44 ||
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08004503 tp->mac_version == RTL_GIGA_MAC_VER_38) {
David S. Miller8decf862011-09-22 03:23:13 -04004504 RTL_W8(ChipCmd, RTL_R8(ChipCmd) | StopReq);
Francois Romieuffc46952012-07-06 14:19:23 +02004505 rtl_udelay_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 666);
Hayes Wang92fc43b2011-07-06 15:58:03 +08004506 } else {
4507 RTL_W8(ChipCmd, RTL_R8(ChipCmd) | StopReq);
4508 udelay(100);
françois romieue6de30d2011-01-03 15:08:37 +00004509 }
4510
Hayes Wang92fc43b2011-07-06 15:58:03 +08004511 rtl_hw_reset(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004512}
4513
Francois Romieu7f796d832007-06-11 23:04:41 +02004514static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp)
Francois Romieu9cb427b2006-11-02 00:10:16 +01004515{
4516 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu9cb427b2006-11-02 00:10:16 +01004517
4518 /* Set DMA burst size and Interframe Gap Time */
4519 RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) |
4520 (InterFrameGap << TxInterFrameGapShift));
4521}
4522
Francois Romieu07ce4062007-02-23 23:36:39 +01004523static void rtl_hw_start(struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004524{
4525 struct rtl8169_private *tp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004526
Francois Romieu07ce4062007-02-23 23:36:39 +01004527 tp->hw_start(dev);
4528
Francois Romieuda78dbf2012-01-26 14:18:23 +01004529 rtl_irq_enable_all(tp);
Francois Romieu07ce4062007-02-23 23:36:39 +01004530}
4531
Francois Romieu7f796d832007-06-11 23:04:41 +02004532static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp,
4533 void __iomem *ioaddr)
4534{
4535 /*
4536 * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh
4537 * register to be written before TxDescAddrLow to work.
4538 * Switching from MMIO to I/O access fixes the issue as well.
4539 */
4540 RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr) >> 32);
Yang Hongyang284901a2009-04-06 19:01:15 -07004541 RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr) & DMA_BIT_MASK(32));
Francois Romieu7f796d832007-06-11 23:04:41 +02004542 RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32);
Yang Hongyang284901a2009-04-06 19:01:15 -07004543 RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_BIT_MASK(32));
Francois Romieu7f796d832007-06-11 23:04:41 +02004544}
4545
4546static u16 rtl_rw_cpluscmd(void __iomem *ioaddr)
4547{
4548 u16 cmd;
4549
4550 cmd = RTL_R16(CPlusCmd);
4551 RTL_W16(CPlusCmd, cmd);
4552 return cmd;
4553}
4554
Eric Dumazetfdd7b4c2009-06-09 04:01:02 -07004555static void rtl_set_rx_max_size(void __iomem *ioaddr, unsigned int rx_buf_sz)
Francois Romieu7f796d832007-06-11 23:04:41 +02004556{
4557 /* Low hurts. Let's disable the filtering. */
Raimonds Cicans207d6e872009-10-26 10:52:37 +00004558 RTL_W16(RxMaxSize, rx_buf_sz + 1);
Francois Romieu7f796d832007-06-11 23:04:41 +02004559}
4560
Francois Romieu6dccd162007-02-13 23:38:05 +01004561static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version)
4562{
Francois Romieu37441002011-06-17 22:58:54 +02004563 static const struct rtl_cfg2_info {
Francois Romieu6dccd162007-02-13 23:38:05 +01004564 u32 mac_version;
4565 u32 clk;
4566 u32 val;
4567 } cfg2_info [] = {
4568 { RTL_GIGA_MAC_VER_05, PCI_Clock_33MHz, 0x000fff00 }, // 8110SCd
4569 { RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff },
4570 { RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe
4571 { RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff }
Francois Romieu37441002011-06-17 22:58:54 +02004572 };
4573 const struct rtl_cfg2_info *p = cfg2_info;
Francois Romieu6dccd162007-02-13 23:38:05 +01004574 unsigned int i;
4575 u32 clk;
4576
4577 clk = RTL_R8(Config2) & PCI_Clock_66MHz;
Francois Romieucadf1852008-01-03 23:38:38 +01004578 for (i = 0; i < ARRAY_SIZE(cfg2_info); i++, p++) {
Francois Romieu6dccd162007-02-13 23:38:05 +01004579 if ((p->mac_version == mac_version) && (p->clk == clk)) {
4580 RTL_W32(0x7c, p->val);
4581 break;
4582 }
4583 }
4584}
4585
Francois Romieue6b763e2012-03-08 09:35:39 +01004586static void rtl_set_rx_mode(struct net_device *dev)
4587{
4588 struct rtl8169_private *tp = netdev_priv(dev);
4589 void __iomem *ioaddr = tp->mmio_addr;
4590 u32 mc_filter[2]; /* Multicast hash filter */
4591 int rx_mode;
4592 u32 tmp = 0;
4593
4594 if (dev->flags & IFF_PROMISC) {
4595 /* Unconditionally log net taps. */
4596 netif_notice(tp, link, dev, "Promiscuous mode enabled\n");
4597 rx_mode =
4598 AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
4599 AcceptAllPhys;
4600 mc_filter[1] = mc_filter[0] = 0xffffffff;
4601 } else if ((netdev_mc_count(dev) > multicast_filter_limit) ||
4602 (dev->flags & IFF_ALLMULTI)) {
4603 /* Too many to filter perfectly -- accept all multicasts. */
4604 rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
4605 mc_filter[1] = mc_filter[0] = 0xffffffff;
4606 } else {
4607 struct netdev_hw_addr *ha;
4608
4609 rx_mode = AcceptBroadcast | AcceptMyPhys;
4610 mc_filter[1] = mc_filter[0] = 0;
4611 netdev_for_each_mc_addr(ha, dev) {
4612 int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26;
4613 mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
4614 rx_mode |= AcceptMulticast;
4615 }
4616 }
4617
4618 if (dev->features & NETIF_F_RXALL)
4619 rx_mode |= (AcceptErr | AcceptRunt);
4620
4621 tmp = (RTL_R32(RxConfig) & ~RX_CONFIG_ACCEPT_MASK) | rx_mode;
4622
4623 if (tp->mac_version > RTL_GIGA_MAC_VER_06) {
4624 u32 data = mc_filter[0];
4625
4626 mc_filter[0] = swab32(mc_filter[1]);
4627 mc_filter[1] = swab32(data);
4628 }
4629
Nathan Walp04817762012-11-01 12:08:47 +00004630 if (tp->mac_version == RTL_GIGA_MAC_VER_35)
4631 mc_filter[1] = mc_filter[0] = 0xffffffff;
4632
Francois Romieue6b763e2012-03-08 09:35:39 +01004633 RTL_W32(MAR0 + 4, mc_filter[1]);
4634 RTL_W32(MAR0 + 0, mc_filter[0]);
4635
4636 RTL_W32(RxConfig, tmp);
4637}
4638
Francois Romieu07ce4062007-02-23 23:36:39 +01004639static void rtl_hw_start_8169(struct net_device *dev)
4640{
4641 struct rtl8169_private *tp = netdev_priv(dev);
4642 void __iomem *ioaddr = tp->mmio_addr;
4643 struct pci_dev *pdev = tp->pci_dev;
Francois Romieu07ce4062007-02-23 23:36:39 +01004644
Francois Romieu9cb427b2006-11-02 00:10:16 +01004645 if (tp->mac_version == RTL_GIGA_MAC_VER_05) {
4646 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW);
4647 pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08);
4648 }
4649
Linus Torvalds1da177e2005-04-16 15:20:36 -07004650 RTL_W8(Cfg9346, Cfg9346_Unlock);
Francois Romieucecb5fd2011-04-01 10:21:07 +02004651 if (tp->mac_version == RTL_GIGA_MAC_VER_01 ||
4652 tp->mac_version == RTL_GIGA_MAC_VER_02 ||
4653 tp->mac_version == RTL_GIGA_MAC_VER_03 ||
4654 tp->mac_version == RTL_GIGA_MAC_VER_04)
Francois Romieu9cb427b2006-11-02 00:10:16 +01004655 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
4656
Hayes Wange542a222011-07-06 15:58:04 +08004657 rtl_init_rxcfg(tp);
4658
françois romieuf0298f82011-01-03 15:07:42 +00004659 RTL_W8(EarlyTxThres, NoEarlyTx);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004660
Eric Dumazet6f0333b2010-10-11 11:17:47 +00004661 rtl_set_rx_max_size(ioaddr, rx_buf_sz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004662
Francois Romieucecb5fd2011-04-01 10:21:07 +02004663 if (tp->mac_version == RTL_GIGA_MAC_VER_01 ||
4664 tp->mac_version == RTL_GIGA_MAC_VER_02 ||
4665 tp->mac_version == RTL_GIGA_MAC_VER_03 ||
4666 tp->mac_version == RTL_GIGA_MAC_VER_04)
Francois Romieuc946b302007-10-04 00:42:50 +02004667 rtl_set_rx_tx_config_registers(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004668
Francois Romieu7f796d832007-06-11 23:04:41 +02004669 tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW;
Francois Romieubcf0bf92006-07-26 23:14:13 +02004670
Francois Romieucecb5fd2011-04-01 10:21:07 +02004671 if (tp->mac_version == RTL_GIGA_MAC_VER_02 ||
4672 tp->mac_version == RTL_GIGA_MAC_VER_03) {
Joe Perches06fa7352007-10-18 21:15:00 +02004673 dprintk("Set MAC Reg C+CR Offset 0xE0. "
Linus Torvalds1da177e2005-04-16 15:20:36 -07004674 "Bit-3 and bit-14 MUST be 1\n");
Francois Romieubcf0bf92006-07-26 23:14:13 +02004675 tp->cp_cmd |= (1 << 14);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004676 }
4677
Francois Romieubcf0bf92006-07-26 23:14:13 +02004678 RTL_W16(CPlusCmd, tp->cp_cmd);
4679
Francois Romieu6dccd162007-02-13 23:38:05 +01004680 rtl8169_set_magic_reg(ioaddr, tp->mac_version);
4681
Linus Torvalds1da177e2005-04-16 15:20:36 -07004682 /*
4683 * Undocumented corner. Supposedly:
4684 * (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets
4685 */
4686 RTL_W16(IntrMitigate, 0x0000);
4687
Francois Romieu7f796d832007-06-11 23:04:41 +02004688 rtl_set_rx_tx_desc_registers(tp, ioaddr);
Francois Romieu9cb427b2006-11-02 00:10:16 +01004689
Francois Romieucecb5fd2011-04-01 10:21:07 +02004690 if (tp->mac_version != RTL_GIGA_MAC_VER_01 &&
4691 tp->mac_version != RTL_GIGA_MAC_VER_02 &&
4692 tp->mac_version != RTL_GIGA_MAC_VER_03 &&
4693 tp->mac_version != RTL_GIGA_MAC_VER_04) {
Francois Romieuc946b302007-10-04 00:42:50 +02004694 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
4695 rtl_set_rx_tx_config_registers(tp);
4696 }
4697
Linus Torvalds1da177e2005-04-16 15:20:36 -07004698 RTL_W8(Cfg9346, Cfg9346_Lock);
Francois Romieub518fa82006-08-16 15:23:13 +02004699
4700 /* Initially a 10 us delay. Turned it into a PCI commit. - FR */
4701 RTL_R8(IntrMask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004702
4703 RTL_W32(RxMissed, 0);
4704
Francois Romieu07ce4062007-02-23 23:36:39 +01004705 rtl_set_rx_mode(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004706
4707 /* no early-rx interrupts */
4708 RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000);
Francois Romieu07ce4062007-02-23 23:36:39 +01004709}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004710
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004711static void rtl_csi_write(struct rtl8169_private *tp, int addr, int value)
4712{
4713 if (tp->csi_ops.write)
Francois Romieu52989f02012-07-06 13:37:00 +02004714 tp->csi_ops.write(tp, addr, value);
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004715}
4716
4717static u32 rtl_csi_read(struct rtl8169_private *tp, int addr)
4718{
Francois Romieu52989f02012-07-06 13:37:00 +02004719 return tp->csi_ops.read ? tp->csi_ops.read(tp, addr) : ~0;
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004720}
4721
4722static void rtl_csi_access_enable(struct rtl8169_private *tp, u32 bits)
Francois Romieudacf8152008-08-02 20:44:13 +02004723{
4724 u32 csi;
4725
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004726 csi = rtl_csi_read(tp, 0x070c) & 0x00ffffff;
4727 rtl_csi_write(tp, 0x070c, csi | bits);
françois romieu650e8d52011-01-03 15:08:29 +00004728}
4729
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004730static void rtl_csi_access_enable_1(struct rtl8169_private *tp)
françois romieue6de30d2011-01-03 15:08:37 +00004731{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004732 rtl_csi_access_enable(tp, 0x17000000);
françois romieue6de30d2011-01-03 15:08:37 +00004733}
4734
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004735static void rtl_csi_access_enable_2(struct rtl8169_private *tp)
françois romieu650e8d52011-01-03 15:08:29 +00004736{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004737 rtl_csi_access_enable(tp, 0x27000000);
4738}
4739
Francois Romieuffc46952012-07-06 14:19:23 +02004740DECLARE_RTL_COND(rtl_csiar_cond)
4741{
4742 void __iomem *ioaddr = tp->mmio_addr;
4743
4744 return RTL_R32(CSIAR) & CSIAR_FLAG;
4745}
4746
Francois Romieu52989f02012-07-06 13:37:00 +02004747static void r8169_csi_write(struct rtl8169_private *tp, int addr, int value)
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004748{
Francois Romieu52989f02012-07-06 13:37:00 +02004749 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004750
4751 RTL_W32(CSIDR, value);
4752 RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) |
4753 CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT);
4754
Francois Romieuffc46952012-07-06 14:19:23 +02004755 rtl_udelay_loop_wait_low(tp, &rtl_csiar_cond, 10, 100);
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004756}
4757
Francois Romieu52989f02012-07-06 13:37:00 +02004758static u32 r8169_csi_read(struct rtl8169_private *tp, int addr)
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004759{
Francois Romieu52989f02012-07-06 13:37:00 +02004760 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004761
4762 RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) |
4763 CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT);
4764
Francois Romieuffc46952012-07-06 14:19:23 +02004765 return rtl_udelay_loop_wait_high(tp, &rtl_csiar_cond, 10, 100) ?
4766 RTL_R32(CSIDR) : ~0;
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004767}
4768
Francois Romieu52989f02012-07-06 13:37:00 +02004769static void r8402_csi_write(struct rtl8169_private *tp, int addr, int value)
Hayes Wang7e18dca2012-03-30 14:33:02 +08004770{
Francois Romieu52989f02012-07-06 13:37:00 +02004771 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang7e18dca2012-03-30 14:33:02 +08004772
4773 RTL_W32(CSIDR, value);
4774 RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) |
4775 CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT |
4776 CSIAR_FUNC_NIC);
4777
Francois Romieuffc46952012-07-06 14:19:23 +02004778 rtl_udelay_loop_wait_low(tp, &rtl_csiar_cond, 10, 100);
Hayes Wang7e18dca2012-03-30 14:33:02 +08004779}
4780
Francois Romieu52989f02012-07-06 13:37:00 +02004781static u32 r8402_csi_read(struct rtl8169_private *tp, int addr)
Hayes Wang7e18dca2012-03-30 14:33:02 +08004782{
Francois Romieu52989f02012-07-06 13:37:00 +02004783 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang7e18dca2012-03-30 14:33:02 +08004784
4785 RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) | CSIAR_FUNC_NIC |
4786 CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT);
4787
Francois Romieuffc46952012-07-06 14:19:23 +02004788 return rtl_udelay_loop_wait_high(tp, &rtl_csiar_cond, 10, 100) ?
4789 RTL_R32(CSIDR) : ~0;
Hayes Wang7e18dca2012-03-30 14:33:02 +08004790}
4791
hayeswang45dd95c2013-07-08 17:09:01 +08004792static void r8411_csi_write(struct rtl8169_private *tp, int addr, int value)
4793{
4794 void __iomem *ioaddr = tp->mmio_addr;
4795
4796 RTL_W32(CSIDR, value);
4797 RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) |
4798 CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT |
4799 CSIAR_FUNC_NIC2);
4800
4801 rtl_udelay_loop_wait_low(tp, &rtl_csiar_cond, 10, 100);
4802}
4803
4804static u32 r8411_csi_read(struct rtl8169_private *tp, int addr)
4805{
4806 void __iomem *ioaddr = tp->mmio_addr;
4807
4808 RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) | CSIAR_FUNC_NIC2 |
4809 CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT);
4810
4811 return rtl_udelay_loop_wait_high(tp, &rtl_csiar_cond, 10, 100) ?
4812 RTL_R32(CSIDR) : ~0;
4813}
4814
Bill Pembertonbaf63292012-12-03 09:23:28 -05004815static void rtl_init_csi_ops(struct rtl8169_private *tp)
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004816{
4817 struct csi_ops *ops = &tp->csi_ops;
4818
4819 switch (tp->mac_version) {
4820 case RTL_GIGA_MAC_VER_01:
4821 case RTL_GIGA_MAC_VER_02:
4822 case RTL_GIGA_MAC_VER_03:
4823 case RTL_GIGA_MAC_VER_04:
4824 case RTL_GIGA_MAC_VER_05:
4825 case RTL_GIGA_MAC_VER_06:
4826 case RTL_GIGA_MAC_VER_10:
4827 case RTL_GIGA_MAC_VER_11:
4828 case RTL_GIGA_MAC_VER_12:
4829 case RTL_GIGA_MAC_VER_13:
4830 case RTL_GIGA_MAC_VER_14:
4831 case RTL_GIGA_MAC_VER_15:
4832 case RTL_GIGA_MAC_VER_16:
4833 case RTL_GIGA_MAC_VER_17:
4834 ops->write = NULL;
4835 ops->read = NULL;
4836 break;
4837
Hayes Wang7e18dca2012-03-30 14:33:02 +08004838 case RTL_GIGA_MAC_VER_37:
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08004839 case RTL_GIGA_MAC_VER_38:
Hayes Wang7e18dca2012-03-30 14:33:02 +08004840 ops->write = r8402_csi_write;
4841 ops->read = r8402_csi_read;
4842 break;
4843
hayeswang45dd95c2013-07-08 17:09:01 +08004844 case RTL_GIGA_MAC_VER_44:
4845 ops->write = r8411_csi_write;
4846 ops->read = r8411_csi_read;
4847 break;
4848
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004849 default:
4850 ops->write = r8169_csi_write;
4851 ops->read = r8169_csi_read;
4852 break;
4853 }
Francois Romieudacf8152008-08-02 20:44:13 +02004854}
4855
4856struct ephy_info {
4857 unsigned int offset;
4858 u16 mask;
4859 u16 bits;
4860};
4861
Francois Romieufdf6fc02012-07-06 22:40:38 +02004862static void rtl_ephy_init(struct rtl8169_private *tp, const struct ephy_info *e,
4863 int len)
Francois Romieudacf8152008-08-02 20:44:13 +02004864{
4865 u16 w;
4866
4867 while (len-- > 0) {
Francois Romieufdf6fc02012-07-06 22:40:38 +02004868 w = (rtl_ephy_read(tp, e->offset) & ~e->mask) | e->bits;
4869 rtl_ephy_write(tp, e->offset, w);
Francois Romieudacf8152008-08-02 20:44:13 +02004870 e++;
4871 }
4872}
4873
Francois Romieub726e492008-06-28 12:22:59 +02004874static void rtl_disable_clock_request(struct pci_dev *pdev)
4875{
Jiang Liu7d7903b2012-07-24 17:20:16 +08004876 pcie_capability_clear_word(pdev, PCI_EXP_LNKCTL,
4877 PCI_EXP_LNKCTL_CLKREQ_EN);
Francois Romieub726e492008-06-28 12:22:59 +02004878}
4879
françois romieue6de30d2011-01-03 15:08:37 +00004880static void rtl_enable_clock_request(struct pci_dev *pdev)
4881{
Jiang Liu7d7903b2012-07-24 17:20:16 +08004882 pcie_capability_set_word(pdev, PCI_EXP_LNKCTL,
4883 PCI_EXP_LNKCTL_CLKREQ_EN);
françois romieue6de30d2011-01-03 15:08:37 +00004884}
4885
Francois Romieub726e492008-06-28 12:22:59 +02004886#define R8168_CPCMD_QUIRK_MASK (\
4887 EnableBist | \
4888 Mac_dbgo_oe | \
4889 Force_half_dup | \
4890 Force_rxflow_en | \
4891 Force_txflow_en | \
4892 Cxpl_dbg_sel | \
4893 ASF | \
4894 PktCntrDisable | \
4895 Mac_dbgo_sel)
4896
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004897static void rtl_hw_start_8168bb(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004898{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004899 void __iomem *ioaddr = tp->mmio_addr;
4900 struct pci_dev *pdev = tp->pci_dev;
4901
Francois Romieub726e492008-06-28 12:22:59 +02004902 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
4903
4904 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
4905
françois romieufaf1e782013-02-27 13:01:57 +00004906 if (tp->dev->mtu <= ETH_DATA_LEN) {
4907 rtl_tx_performance_tweak(pdev, (0x5 << MAX_READ_REQUEST_SHIFT) |
4908 PCI_EXP_DEVCTL_NOSNOOP_EN);
4909 }
Francois Romieu219a1e92008-06-28 11:58:39 +02004910}
4911
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004912static void rtl_hw_start_8168bef(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004913{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004914 void __iomem *ioaddr = tp->mmio_addr;
4915
4916 rtl_hw_start_8168bb(tp);
Francois Romieub726e492008-06-28 12:22:59 +02004917
françois romieuf0298f82011-01-03 15:07:42 +00004918 RTL_W8(MaxTxPacketSize, TxPacketMax);
Francois Romieub726e492008-06-28 12:22:59 +02004919
4920 RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0));
Francois Romieu219a1e92008-06-28 11:58:39 +02004921}
4922
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004923static void __rtl_hw_start_8168cp(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004924{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004925 void __iomem *ioaddr = tp->mmio_addr;
4926 struct pci_dev *pdev = tp->pci_dev;
4927
Francois Romieub726e492008-06-28 12:22:59 +02004928 RTL_W8(Config1, RTL_R8(Config1) | Speed_down);
4929
4930 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
4931
françois romieufaf1e782013-02-27 13:01:57 +00004932 if (tp->dev->mtu <= ETH_DATA_LEN)
4933 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
Francois Romieub726e492008-06-28 12:22:59 +02004934
4935 rtl_disable_clock_request(pdev);
4936
4937 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
Francois Romieu219a1e92008-06-28 11:58:39 +02004938}
4939
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004940static void rtl_hw_start_8168cp_1(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004941{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08004942 static const struct ephy_info e_info_8168cp[] = {
Francois Romieub726e492008-06-28 12:22:59 +02004943 { 0x01, 0, 0x0001 },
4944 { 0x02, 0x0800, 0x1000 },
4945 { 0x03, 0, 0x0042 },
4946 { 0x06, 0x0080, 0x0000 },
4947 { 0x07, 0, 0x2000 }
4948 };
4949
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004950 rtl_csi_access_enable_2(tp);
Francois Romieub726e492008-06-28 12:22:59 +02004951
Francois Romieufdf6fc02012-07-06 22:40:38 +02004952 rtl_ephy_init(tp, e_info_8168cp, ARRAY_SIZE(e_info_8168cp));
Francois Romieub726e492008-06-28 12:22:59 +02004953
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004954 __rtl_hw_start_8168cp(tp);
Francois Romieu219a1e92008-06-28 11:58:39 +02004955}
4956
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004957static void rtl_hw_start_8168cp_2(struct rtl8169_private *tp)
Francois Romieuef3386f2008-06-29 12:24:30 +02004958{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004959 void __iomem *ioaddr = tp->mmio_addr;
4960 struct pci_dev *pdev = tp->pci_dev;
4961
4962 rtl_csi_access_enable_2(tp);
Francois Romieuef3386f2008-06-29 12:24:30 +02004963
4964 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
4965
françois romieufaf1e782013-02-27 13:01:57 +00004966 if (tp->dev->mtu <= ETH_DATA_LEN)
4967 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
Francois Romieuef3386f2008-06-29 12:24:30 +02004968
4969 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
4970}
4971
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004972static void rtl_hw_start_8168cp_3(struct rtl8169_private *tp)
Francois Romieu7f3e3d32008-07-20 18:53:20 +02004973{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004974 void __iomem *ioaddr = tp->mmio_addr;
4975 struct pci_dev *pdev = tp->pci_dev;
4976
4977 rtl_csi_access_enable_2(tp);
Francois Romieu7f3e3d32008-07-20 18:53:20 +02004978
4979 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
4980
4981 /* Magic. */
4982 RTL_W8(DBG_REG, 0x20);
4983
françois romieuf0298f82011-01-03 15:07:42 +00004984 RTL_W8(MaxTxPacketSize, TxPacketMax);
Francois Romieu7f3e3d32008-07-20 18:53:20 +02004985
françois romieufaf1e782013-02-27 13:01:57 +00004986 if (tp->dev->mtu <= ETH_DATA_LEN)
4987 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
Francois Romieu7f3e3d32008-07-20 18:53:20 +02004988
4989 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
4990}
4991
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004992static void rtl_hw_start_8168c_1(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02004993{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08004994 void __iomem *ioaddr = tp->mmio_addr;
Alexey Dobriyan350f7592009-11-25 15:54:21 -08004995 static const struct ephy_info e_info_8168c_1[] = {
Francois Romieub726e492008-06-28 12:22:59 +02004996 { 0x02, 0x0800, 0x1000 },
4997 { 0x03, 0, 0x0002 },
4998 { 0x06, 0x0080, 0x0000 }
4999 };
5000
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005001 rtl_csi_access_enable_2(tp);
Francois Romieub726e492008-06-28 12:22:59 +02005002
5003 RTL_W8(DBG_REG, 0x06 | FIX_NAK_1 | FIX_NAK_2);
5004
Francois Romieufdf6fc02012-07-06 22:40:38 +02005005 rtl_ephy_init(tp, e_info_8168c_1, ARRAY_SIZE(e_info_8168c_1));
Francois Romieub726e492008-06-28 12:22:59 +02005006
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005007 __rtl_hw_start_8168cp(tp);
Francois Romieu219a1e92008-06-28 11:58:39 +02005008}
5009
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005010static void rtl_hw_start_8168c_2(struct rtl8169_private *tp)
Francois Romieu219a1e92008-06-28 11:58:39 +02005011{
Alexey Dobriyan350f7592009-11-25 15:54:21 -08005012 static const struct ephy_info e_info_8168c_2[] = {
Francois Romieub726e492008-06-28 12:22:59 +02005013 { 0x01, 0, 0x0001 },
5014 { 0x03, 0x0400, 0x0220 }
5015 };
5016
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005017 rtl_csi_access_enable_2(tp);
Francois Romieub726e492008-06-28 12:22:59 +02005018
Francois Romieufdf6fc02012-07-06 22:40:38 +02005019 rtl_ephy_init(tp, e_info_8168c_2, ARRAY_SIZE(e_info_8168c_2));
Francois Romieub726e492008-06-28 12:22:59 +02005020
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005021 __rtl_hw_start_8168cp(tp);
Francois Romieu219a1e92008-06-28 11:58:39 +02005022}
5023
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005024static void rtl_hw_start_8168c_3(struct rtl8169_private *tp)
Francois Romieu197ff762008-06-28 13:16:02 +02005025{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005026 rtl_hw_start_8168c_2(tp);
Francois Romieu197ff762008-06-28 13:16:02 +02005027}
5028
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005029static void rtl_hw_start_8168c_4(struct rtl8169_private *tp)
Francois Romieu6fb07052008-06-29 11:54:28 +02005030{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005031 rtl_csi_access_enable_2(tp);
Francois Romieu6fb07052008-06-29 11:54:28 +02005032
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005033 __rtl_hw_start_8168cp(tp);
Francois Romieu6fb07052008-06-29 11:54:28 +02005034}
5035
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005036static void rtl_hw_start_8168d(struct rtl8169_private *tp)
Francois Romieu5b538df2008-07-20 16:22:45 +02005037{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005038 void __iomem *ioaddr = tp->mmio_addr;
5039 struct pci_dev *pdev = tp->pci_dev;
5040
5041 rtl_csi_access_enable_2(tp);
Francois Romieu5b538df2008-07-20 16:22:45 +02005042
5043 rtl_disable_clock_request(pdev);
5044
françois romieuf0298f82011-01-03 15:07:42 +00005045 RTL_W8(MaxTxPacketSize, TxPacketMax);
Francois Romieu5b538df2008-07-20 16:22:45 +02005046
françois romieufaf1e782013-02-27 13:01:57 +00005047 if (tp->dev->mtu <= ETH_DATA_LEN)
5048 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
Francois Romieu5b538df2008-07-20 16:22:45 +02005049
5050 RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK);
5051}
5052
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005053static void rtl_hw_start_8168dp(struct rtl8169_private *tp)
hayeswang4804b3b2011-03-21 01:50:29 +00005054{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005055 void __iomem *ioaddr = tp->mmio_addr;
5056 struct pci_dev *pdev = tp->pci_dev;
5057
5058 rtl_csi_access_enable_1(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005059
françois romieufaf1e782013-02-27 13:01:57 +00005060 if (tp->dev->mtu <= ETH_DATA_LEN)
5061 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
hayeswang4804b3b2011-03-21 01:50:29 +00005062
5063 RTL_W8(MaxTxPacketSize, TxPacketMax);
5064
5065 rtl_disable_clock_request(pdev);
5066}
5067
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005068static void rtl_hw_start_8168d_4(struct rtl8169_private *tp)
françois romieue6de30d2011-01-03 15:08:37 +00005069{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005070 void __iomem *ioaddr = tp->mmio_addr;
5071 struct pci_dev *pdev = tp->pci_dev;
françois romieue6de30d2011-01-03 15:08:37 +00005072 static const struct ephy_info e_info_8168d_4[] = {
5073 { 0x0b, ~0, 0x48 },
5074 { 0x19, 0x20, 0x50 },
5075 { 0x0c, ~0, 0x20 }
5076 };
5077 int i;
5078
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005079 rtl_csi_access_enable_1(tp);
françois romieue6de30d2011-01-03 15:08:37 +00005080
5081 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5082
5083 RTL_W8(MaxTxPacketSize, TxPacketMax);
5084
5085 for (i = 0; i < ARRAY_SIZE(e_info_8168d_4); i++) {
5086 const struct ephy_info *e = e_info_8168d_4 + i;
5087 u16 w;
5088
Francois Romieufdf6fc02012-07-06 22:40:38 +02005089 w = rtl_ephy_read(tp, e->offset);
5090 rtl_ephy_write(tp, 0x03, (w & e->mask) | e->bits);
françois romieue6de30d2011-01-03 15:08:37 +00005091 }
5092
5093 rtl_enable_clock_request(pdev);
5094}
5095
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005096static void rtl_hw_start_8168e_1(struct rtl8169_private *tp)
hayeswang01dc7fe2011-03-21 01:50:28 +00005097{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005098 void __iomem *ioaddr = tp->mmio_addr;
5099 struct pci_dev *pdev = tp->pci_dev;
Hayes Wang70090422011-07-06 15:58:06 +08005100 static const struct ephy_info e_info_8168e_1[] = {
hayeswang01dc7fe2011-03-21 01:50:28 +00005101 { 0x00, 0x0200, 0x0100 },
5102 { 0x00, 0x0000, 0x0004 },
5103 { 0x06, 0x0002, 0x0001 },
5104 { 0x06, 0x0000, 0x0030 },
5105 { 0x07, 0x0000, 0x2000 },
5106 { 0x00, 0x0000, 0x0020 },
5107 { 0x03, 0x5800, 0x2000 },
5108 { 0x03, 0x0000, 0x0001 },
5109 { 0x01, 0x0800, 0x1000 },
5110 { 0x07, 0x0000, 0x4000 },
5111 { 0x1e, 0x0000, 0x2000 },
5112 { 0x19, 0xffff, 0xfe6c },
5113 { 0x0a, 0x0000, 0x0040 }
5114 };
5115
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005116 rtl_csi_access_enable_2(tp);
hayeswang01dc7fe2011-03-21 01:50:28 +00005117
Francois Romieufdf6fc02012-07-06 22:40:38 +02005118 rtl_ephy_init(tp, e_info_8168e_1, ARRAY_SIZE(e_info_8168e_1));
hayeswang01dc7fe2011-03-21 01:50:28 +00005119
françois romieufaf1e782013-02-27 13:01:57 +00005120 if (tp->dev->mtu <= ETH_DATA_LEN)
5121 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
hayeswang01dc7fe2011-03-21 01:50:28 +00005122
5123 RTL_W8(MaxTxPacketSize, TxPacketMax);
5124
5125 rtl_disable_clock_request(pdev);
5126
5127 /* Reset tx FIFO pointer */
Francois Romieucecb5fd2011-04-01 10:21:07 +02005128 RTL_W32(MISC, RTL_R32(MISC) | TXPLA_RST);
5129 RTL_W32(MISC, RTL_R32(MISC) & ~TXPLA_RST);
hayeswang01dc7fe2011-03-21 01:50:28 +00005130
Francois Romieucecb5fd2011-04-01 10:21:07 +02005131 RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en);
hayeswang01dc7fe2011-03-21 01:50:28 +00005132}
5133
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005134static void rtl_hw_start_8168e_2(struct rtl8169_private *tp)
Hayes Wang70090422011-07-06 15:58:06 +08005135{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005136 void __iomem *ioaddr = tp->mmio_addr;
5137 struct pci_dev *pdev = tp->pci_dev;
Hayes Wang70090422011-07-06 15:58:06 +08005138 static const struct ephy_info e_info_8168e_2[] = {
5139 { 0x09, 0x0000, 0x0080 },
5140 { 0x19, 0x0000, 0x0224 }
5141 };
5142
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005143 rtl_csi_access_enable_1(tp);
Hayes Wang70090422011-07-06 15:58:06 +08005144
Francois Romieufdf6fc02012-07-06 22:40:38 +02005145 rtl_ephy_init(tp, e_info_8168e_2, ARRAY_SIZE(e_info_8168e_2));
Hayes Wang70090422011-07-06 15:58:06 +08005146
françois romieufaf1e782013-02-27 13:01:57 +00005147 if (tp->dev->mtu <= ETH_DATA_LEN)
5148 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
Hayes Wang70090422011-07-06 15:58:06 +08005149
Francois Romieufdf6fc02012-07-06 22:40:38 +02005150 rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5151 rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5152 rtl_eri_write(tp, 0xc8, ERIAR_MASK_1111, 0x00100002, ERIAR_EXGMAC);
5153 rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC);
5154 rtl_eri_write(tp, 0xcc, ERIAR_MASK_1111, 0x00000050, ERIAR_EXGMAC);
5155 rtl_eri_write(tp, 0xd0, ERIAR_MASK_1111, 0x07ff0060, ERIAR_EXGMAC);
5156 rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC);
5157 rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0xff00, ERIAR_EXGMAC);
Hayes Wang70090422011-07-06 15:58:06 +08005158
Hayes Wang3090bd92011-09-06 16:55:15 +08005159 RTL_W8(MaxTxPacketSize, EarlySize);
Hayes Wang70090422011-07-06 15:58:06 +08005160
Francois Romieu4521e1a92012-11-01 16:46:28 +00005161 rtl_disable_clock_request(pdev);
5162
Hayes Wang70090422011-07-06 15:58:06 +08005163 RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
5164 RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
5165
5166 /* Adjust EEE LED frequency */
5167 RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07);
5168
5169 RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
5170 RTL_W32(MISC, RTL_R32(MISC) | PWM_EN);
Francois Romieu4521e1a92012-11-01 16:46:28 +00005171 RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en);
Hayes Wang70090422011-07-06 15:58:06 +08005172}
5173
Hayes Wang5f886e02012-03-30 14:33:03 +08005174static void rtl_hw_start_8168f(struct rtl8169_private *tp)
Hayes Wangc2218922011-09-06 16:55:18 +08005175{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005176 void __iomem *ioaddr = tp->mmio_addr;
5177 struct pci_dev *pdev = tp->pci_dev;
Hayes Wangc2218922011-09-06 16:55:18 +08005178
Hayes Wang5f886e02012-03-30 14:33:03 +08005179 rtl_csi_access_enable_2(tp);
Hayes Wangc2218922011-09-06 16:55:18 +08005180
5181 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5182
Francois Romieufdf6fc02012-07-06 22:40:38 +02005183 rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5184 rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5185 rtl_eri_write(tp, 0xc8, ERIAR_MASK_1111, 0x00100002, ERIAR_EXGMAC);
5186 rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC);
5187 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC);
5188 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC);
5189 rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC);
5190 rtl_w1w0_eri(tp, 0x1d0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC);
5191 rtl_eri_write(tp, 0xcc, ERIAR_MASK_1111, 0x00000050, ERIAR_EXGMAC);
5192 rtl_eri_write(tp, 0xd0, ERIAR_MASK_1111, 0x00000060, ERIAR_EXGMAC);
Hayes Wangc2218922011-09-06 16:55:18 +08005193
5194 RTL_W8(MaxTxPacketSize, EarlySize);
5195
Francois Romieu4521e1a92012-11-01 16:46:28 +00005196 rtl_disable_clock_request(pdev);
5197
Hayes Wangc2218922011-09-06 16:55:18 +08005198 RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
5199 RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
Hayes Wangc2218922011-09-06 16:55:18 +08005200 RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
Francois Romieu4521e1a92012-11-01 16:46:28 +00005201 RTL_W32(MISC, RTL_R32(MISC) | PWM_EN);
5202 RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en);
Hayes Wangc2218922011-09-06 16:55:18 +08005203}
5204
Hayes Wang5f886e02012-03-30 14:33:03 +08005205static void rtl_hw_start_8168f_1(struct rtl8169_private *tp)
5206{
5207 void __iomem *ioaddr = tp->mmio_addr;
5208 static const struct ephy_info e_info_8168f_1[] = {
5209 { 0x06, 0x00c0, 0x0020 },
5210 { 0x08, 0x0001, 0x0002 },
5211 { 0x09, 0x0000, 0x0080 },
5212 { 0x19, 0x0000, 0x0224 }
5213 };
5214
5215 rtl_hw_start_8168f(tp);
5216
Francois Romieufdf6fc02012-07-06 22:40:38 +02005217 rtl_ephy_init(tp, e_info_8168f_1, ARRAY_SIZE(e_info_8168f_1));
Hayes Wang5f886e02012-03-30 14:33:03 +08005218
Francois Romieufdf6fc02012-07-06 22:40:38 +02005219 rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0xff00, ERIAR_EXGMAC);
Hayes Wang5f886e02012-03-30 14:33:03 +08005220
5221 /* Adjust EEE LED frequency */
5222 RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07);
5223}
5224
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005225static void rtl_hw_start_8411(struct rtl8169_private *tp)
5226{
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005227 static const struct ephy_info e_info_8168f_1[] = {
5228 { 0x06, 0x00c0, 0x0020 },
5229 { 0x0f, 0xffff, 0x5200 },
5230 { 0x1e, 0x0000, 0x4000 },
5231 { 0x19, 0x0000, 0x0224 }
5232 };
5233
5234 rtl_hw_start_8168f(tp);
5235
Francois Romieufdf6fc02012-07-06 22:40:38 +02005236 rtl_ephy_init(tp, e_info_8168f_1, ARRAY_SIZE(e_info_8168f_1));
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005237
Francois Romieufdf6fc02012-07-06 22:40:38 +02005238 rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0x0000, ERIAR_EXGMAC);
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005239}
5240
Hayes Wangc5583862012-07-02 17:23:22 +08005241static void rtl_hw_start_8168g_1(struct rtl8169_private *tp)
5242{
5243 void __iomem *ioaddr = tp->mmio_addr;
5244 struct pci_dev *pdev = tp->pci_dev;
5245
hayeswangbeb330a2013-04-01 22:23:39 +00005246 RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
5247
Hayes Wangc5583862012-07-02 17:23:22 +08005248 rtl_eri_write(tp, 0xc8, ERIAR_MASK_0101, 0x080002, ERIAR_EXGMAC);
5249 rtl_eri_write(tp, 0xcc, ERIAR_MASK_0001, 0x38, ERIAR_EXGMAC);
5250 rtl_eri_write(tp, 0xd0, ERIAR_MASK_0001, 0x48, ERIAR_EXGMAC);
5251 rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC);
5252
5253 rtl_csi_access_enable_1(tp);
5254
5255 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5256
5257 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC);
5258 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC);
hayeswangbeb330a2013-04-01 22:23:39 +00005259 rtl_eri_write(tp, 0x2f8, ERIAR_MASK_0011, 0x1d8f, ERIAR_EXGMAC);
Hayes Wangc5583862012-07-02 17:23:22 +08005260
5261 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
Francois Romieu4521e1a92012-11-01 16:46:28 +00005262 RTL_W32(MISC, RTL_R32(MISC) & ~RXDV_GATED_EN);
Hayes Wangc5583862012-07-02 17:23:22 +08005263 RTL_W8(MaxTxPacketSize, EarlySize);
5264
5265 rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5266 rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5267
5268 /* Adjust EEE LED frequency */
5269 RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07);
5270
hayeswangbeb330a2013-04-01 22:23:39 +00005271 rtl_w1w0_eri(tp, 0x2fc, ERIAR_MASK_0001, 0x01, 0x06, ERIAR_EXGMAC);
5272 rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_0011, 0x0000, 0x1000, ERIAR_EXGMAC);
Hayes Wangc5583862012-07-02 17:23:22 +08005273}
5274
hayeswang57538c42013-04-01 22:23:40 +00005275static void rtl_hw_start_8168g_2(struct rtl8169_private *tp)
5276{
5277 void __iomem *ioaddr = tp->mmio_addr;
5278 static const struct ephy_info e_info_8168g_2[] = {
5279 { 0x00, 0x0000, 0x0008 },
5280 { 0x0c, 0x3df0, 0x0200 },
5281 { 0x19, 0xffff, 0xfc00 },
5282 { 0x1e, 0xffff, 0x20eb }
5283 };
5284
5285 rtl_hw_start_8168g_1(tp);
5286
5287 /* disable aspm and clock request before access ephy */
5288 RTL_W8(Config2, RTL_R8(Config2) & ~ClkReqEn);
5289 RTL_W8(Config5, RTL_R8(Config5) & ~ASPM_en);
5290 rtl_ephy_init(tp, e_info_8168g_2, ARRAY_SIZE(e_info_8168g_2));
5291}
5292
hayeswang45dd95c2013-07-08 17:09:01 +08005293static void rtl_hw_start_8411_2(struct rtl8169_private *tp)
5294{
5295 void __iomem *ioaddr = tp->mmio_addr;
5296 static const struct ephy_info e_info_8411_2[] = {
5297 { 0x00, 0x0000, 0x0008 },
5298 { 0x0c, 0x3df0, 0x0200 },
5299 { 0x0f, 0xffff, 0x5200 },
5300 { 0x19, 0x0020, 0x0000 },
5301 { 0x1e, 0x0000, 0x2000 }
5302 };
5303
5304 rtl_hw_start_8168g_1(tp);
5305
5306 /* disable aspm and clock request before access ephy */
5307 RTL_W8(Config2, RTL_R8(Config2) & ~ClkReqEn);
5308 RTL_W8(Config5, RTL_R8(Config5) & ~ASPM_en);
5309 rtl_ephy_init(tp, e_info_8411_2, ARRAY_SIZE(e_info_8411_2));
5310}
5311
Francois Romieu07ce4062007-02-23 23:36:39 +01005312static void rtl_hw_start_8168(struct net_device *dev)
5313{
Francois Romieu2dd99532007-06-11 23:22:52 +02005314 struct rtl8169_private *tp = netdev_priv(dev);
5315 void __iomem *ioaddr = tp->mmio_addr;
5316
5317 RTL_W8(Cfg9346, Cfg9346_Unlock);
5318
françois romieuf0298f82011-01-03 15:07:42 +00005319 RTL_W8(MaxTxPacketSize, TxPacketMax);
Francois Romieu2dd99532007-06-11 23:22:52 +02005320
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005321 rtl_set_rx_max_size(ioaddr, rx_buf_sz);
Francois Romieu2dd99532007-06-11 23:22:52 +02005322
Francois Romieu0e485152007-02-20 00:00:26 +01005323 tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1;
Francois Romieu2dd99532007-06-11 23:22:52 +02005324
5325 RTL_W16(CPlusCmd, tp->cp_cmd);
5326
Francois Romieu0e485152007-02-20 00:00:26 +01005327 RTL_W16(IntrMitigate, 0x5151);
5328
5329 /* Work around for RxFIFO overflow. */
françois romieu811fd302011-12-04 20:30:45 +00005330 if (tp->mac_version == RTL_GIGA_MAC_VER_11) {
Francois Romieuda78dbf2012-01-26 14:18:23 +01005331 tp->event_slow |= RxFIFOOver | PCSTimeout;
5332 tp->event_slow &= ~RxOverflow;
Francois Romieu0e485152007-02-20 00:00:26 +01005333 }
Francois Romieu2dd99532007-06-11 23:22:52 +02005334
5335 rtl_set_rx_tx_desc_registers(tp, ioaddr);
5336
hayeswang1a964642013-04-01 22:23:41 +00005337 rtl_set_rx_tx_config_registers(tp);
Francois Romieu2dd99532007-06-11 23:22:52 +02005338
5339 RTL_R8(IntrMask);
5340
Francois Romieu219a1e92008-06-28 11:58:39 +02005341 switch (tp->mac_version) {
5342 case RTL_GIGA_MAC_VER_11:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005343 rtl_hw_start_8168bb(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005344 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005345
5346 case RTL_GIGA_MAC_VER_12:
5347 case RTL_GIGA_MAC_VER_17:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005348 rtl_hw_start_8168bef(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005349 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005350
5351 case RTL_GIGA_MAC_VER_18:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005352 rtl_hw_start_8168cp_1(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005353 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005354
5355 case RTL_GIGA_MAC_VER_19:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005356 rtl_hw_start_8168c_1(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005357 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005358
5359 case RTL_GIGA_MAC_VER_20:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005360 rtl_hw_start_8168c_2(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005361 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005362
Francois Romieu197ff762008-06-28 13:16:02 +02005363 case RTL_GIGA_MAC_VER_21:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005364 rtl_hw_start_8168c_3(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005365 break;
Francois Romieu197ff762008-06-28 13:16:02 +02005366
Francois Romieu6fb07052008-06-29 11:54:28 +02005367 case RTL_GIGA_MAC_VER_22:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005368 rtl_hw_start_8168c_4(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005369 break;
Francois Romieu6fb07052008-06-29 11:54:28 +02005370
Francois Romieuef3386f2008-06-29 12:24:30 +02005371 case RTL_GIGA_MAC_VER_23:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005372 rtl_hw_start_8168cp_2(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005373 break;
Francois Romieuef3386f2008-06-29 12:24:30 +02005374
Francois Romieu7f3e3d32008-07-20 18:53:20 +02005375 case RTL_GIGA_MAC_VER_24:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005376 rtl_hw_start_8168cp_3(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005377 break;
Francois Romieu7f3e3d32008-07-20 18:53:20 +02005378
Francois Romieu5b538df2008-07-20 16:22:45 +02005379 case RTL_GIGA_MAC_VER_25:
françois romieudaf9df62009-10-07 12:44:20 +00005380 case RTL_GIGA_MAC_VER_26:
5381 case RTL_GIGA_MAC_VER_27:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005382 rtl_hw_start_8168d(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005383 break;
Francois Romieu5b538df2008-07-20 16:22:45 +02005384
françois romieue6de30d2011-01-03 15:08:37 +00005385 case RTL_GIGA_MAC_VER_28:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005386 rtl_hw_start_8168d_4(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005387 break;
Francois Romieucecb5fd2011-04-01 10:21:07 +02005388
hayeswang4804b3b2011-03-21 01:50:29 +00005389 case RTL_GIGA_MAC_VER_31:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005390 rtl_hw_start_8168dp(tp);
hayeswang4804b3b2011-03-21 01:50:29 +00005391 break;
5392
hayeswang01dc7fe2011-03-21 01:50:28 +00005393 case RTL_GIGA_MAC_VER_32:
5394 case RTL_GIGA_MAC_VER_33:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005395 rtl_hw_start_8168e_1(tp);
Hayes Wang70090422011-07-06 15:58:06 +08005396 break;
5397 case RTL_GIGA_MAC_VER_34:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005398 rtl_hw_start_8168e_2(tp);
hayeswang01dc7fe2011-03-21 01:50:28 +00005399 break;
françois romieue6de30d2011-01-03 15:08:37 +00005400
Hayes Wangc2218922011-09-06 16:55:18 +08005401 case RTL_GIGA_MAC_VER_35:
5402 case RTL_GIGA_MAC_VER_36:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005403 rtl_hw_start_8168f_1(tp);
Hayes Wangc2218922011-09-06 16:55:18 +08005404 break;
5405
Hayes Wangb3d7b2f2012-03-30 14:48:06 +08005406 case RTL_GIGA_MAC_VER_38:
5407 rtl_hw_start_8411(tp);
5408 break;
5409
Hayes Wangc5583862012-07-02 17:23:22 +08005410 case RTL_GIGA_MAC_VER_40:
5411 case RTL_GIGA_MAC_VER_41:
5412 rtl_hw_start_8168g_1(tp);
5413 break;
hayeswang57538c42013-04-01 22:23:40 +00005414 case RTL_GIGA_MAC_VER_42:
5415 rtl_hw_start_8168g_2(tp);
5416 break;
Hayes Wangc5583862012-07-02 17:23:22 +08005417
hayeswang45dd95c2013-07-08 17:09:01 +08005418 case RTL_GIGA_MAC_VER_44:
5419 rtl_hw_start_8411_2(tp);
5420 break;
5421
Francois Romieu219a1e92008-06-28 11:58:39 +02005422 default:
5423 printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n",
5424 dev->name, tp->mac_version);
hayeswang4804b3b2011-03-21 01:50:29 +00005425 break;
Francois Romieu219a1e92008-06-28 11:58:39 +02005426 }
Francois Romieu2dd99532007-06-11 23:22:52 +02005427
hayeswang1a964642013-04-01 22:23:41 +00005428 RTL_W8(Cfg9346, Cfg9346_Lock);
5429
Francois Romieu0e485152007-02-20 00:00:26 +01005430 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
5431
hayeswang1a964642013-04-01 22:23:41 +00005432 rtl_set_rx_mode(dev);
Francois Romieub8363902008-06-01 12:31:57 +02005433
Francois Romieu2dd99532007-06-11 23:22:52 +02005434 RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000);
Francois Romieu07ce4062007-02-23 23:36:39 +01005435}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005436
Francois Romieu2857ffb2008-08-02 21:08:49 +02005437#define R810X_CPCMD_QUIRK_MASK (\
5438 EnableBist | \
5439 Mac_dbgo_oe | \
5440 Force_half_dup | \
françois romieu5edcc532009-08-10 19:41:52 +00005441 Force_rxflow_en | \
Francois Romieu2857ffb2008-08-02 21:08:49 +02005442 Force_txflow_en | \
5443 Cxpl_dbg_sel | \
5444 ASF | \
5445 PktCntrDisable | \
Hayes Wangd24e9aa2011-02-22 17:26:19 +08005446 Mac_dbgo_sel)
Francois Romieu2857ffb2008-08-02 21:08:49 +02005447
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005448static void rtl_hw_start_8102e_1(struct rtl8169_private *tp)
Francois Romieu2857ffb2008-08-02 21:08:49 +02005449{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005450 void __iomem *ioaddr = tp->mmio_addr;
5451 struct pci_dev *pdev = tp->pci_dev;
Alexey Dobriyan350f7592009-11-25 15:54:21 -08005452 static const struct ephy_info e_info_8102e_1[] = {
Francois Romieu2857ffb2008-08-02 21:08:49 +02005453 { 0x01, 0, 0x6e65 },
5454 { 0x02, 0, 0x091f },
5455 { 0x03, 0, 0xc2f9 },
5456 { 0x06, 0, 0xafb5 },
5457 { 0x07, 0, 0x0e00 },
5458 { 0x19, 0, 0xec80 },
5459 { 0x01, 0, 0x2e65 },
5460 { 0x01, 0, 0x6e65 }
5461 };
5462 u8 cfg1;
5463
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005464 rtl_csi_access_enable_2(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005465
5466 RTL_W8(DBG_REG, FIX_NAK_1);
5467
5468 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5469
5470 RTL_W8(Config1,
5471 LEDS1 | LEDS0 | Speed_down | MEMMAP | IOMAP | VPD | PMEnable);
5472 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
5473
5474 cfg1 = RTL_R8(Config1);
5475 if ((cfg1 & LEDS0) && (cfg1 & LEDS1))
5476 RTL_W8(Config1, cfg1 & ~LEDS0);
5477
Francois Romieufdf6fc02012-07-06 22:40:38 +02005478 rtl_ephy_init(tp, e_info_8102e_1, ARRAY_SIZE(e_info_8102e_1));
Francois Romieu2857ffb2008-08-02 21:08:49 +02005479}
5480
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005481static void rtl_hw_start_8102e_2(struct rtl8169_private *tp)
Francois Romieu2857ffb2008-08-02 21:08:49 +02005482{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005483 void __iomem *ioaddr = tp->mmio_addr;
5484 struct pci_dev *pdev = tp->pci_dev;
5485
5486 rtl_csi_access_enable_2(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005487
5488 rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT);
5489
5490 RTL_W8(Config1, MEMMAP | IOMAP | VPD | PMEnable);
5491 RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005492}
5493
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005494static void rtl_hw_start_8102e_3(struct rtl8169_private *tp)
Francois Romieu2857ffb2008-08-02 21:08:49 +02005495{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005496 rtl_hw_start_8102e_2(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005497
Francois Romieufdf6fc02012-07-06 22:40:38 +02005498 rtl_ephy_write(tp, 0x03, 0xc2f9);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005499}
5500
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005501static void rtl_hw_start_8105e_1(struct rtl8169_private *tp)
Hayes Wang5a5e4442011-02-22 17:26:21 +08005502{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005503 void __iomem *ioaddr = tp->mmio_addr;
Hayes Wang5a5e4442011-02-22 17:26:21 +08005504 static const struct ephy_info e_info_8105e_1[] = {
5505 { 0x07, 0, 0x4000 },
5506 { 0x19, 0, 0x0200 },
5507 { 0x19, 0, 0x0020 },
5508 { 0x1e, 0, 0x2000 },
5509 { 0x03, 0, 0x0001 },
5510 { 0x19, 0, 0x0100 },
5511 { 0x19, 0, 0x0004 },
5512 { 0x0a, 0, 0x0020 }
5513 };
5514
Francois Romieucecb5fd2011-04-01 10:21:07 +02005515 /* Force LAN exit from ASPM if Rx/Tx are not idle */
Hayes Wang5a5e4442011-02-22 17:26:21 +08005516 RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800);
5517
Francois Romieucecb5fd2011-04-01 10:21:07 +02005518 /* Disable Early Tally Counter */
Hayes Wang5a5e4442011-02-22 17:26:21 +08005519 RTL_W32(FuncEvent, RTL_R32(FuncEvent) & ~0x010000);
5520
5521 RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET);
Hayes Wang4f6b00e52011-07-06 15:58:02 +08005522 RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
Hayes Wang5a5e4442011-02-22 17:26:21 +08005523
Francois Romieufdf6fc02012-07-06 22:40:38 +02005524 rtl_ephy_init(tp, e_info_8105e_1, ARRAY_SIZE(e_info_8105e_1));
Hayes Wang5a5e4442011-02-22 17:26:21 +08005525}
5526
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005527static void rtl_hw_start_8105e_2(struct rtl8169_private *tp)
Hayes Wang5a5e4442011-02-22 17:26:21 +08005528{
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005529 rtl_hw_start_8105e_1(tp);
Francois Romieufdf6fc02012-07-06 22:40:38 +02005530 rtl_ephy_write(tp, 0x1e, rtl_ephy_read(tp, 0x1e) | 0x8000);
Hayes Wang5a5e4442011-02-22 17:26:21 +08005531}
5532
Hayes Wang7e18dca2012-03-30 14:33:02 +08005533static void rtl_hw_start_8402(struct rtl8169_private *tp)
5534{
5535 void __iomem *ioaddr = tp->mmio_addr;
5536 static const struct ephy_info e_info_8402[] = {
5537 { 0x19, 0xffff, 0xff64 },
5538 { 0x1e, 0, 0x4000 }
5539 };
5540
5541 rtl_csi_access_enable_2(tp);
5542
5543 /* Force LAN exit from ASPM if Rx/Tx are not idle */
5544 RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800);
5545
5546 RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
5547 RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
5548
Francois Romieufdf6fc02012-07-06 22:40:38 +02005549 rtl_ephy_init(tp, e_info_8402, ARRAY_SIZE(e_info_8402));
Hayes Wang7e18dca2012-03-30 14:33:02 +08005550
5551 rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT);
5552
Francois Romieufdf6fc02012-07-06 22:40:38 +02005553 rtl_eri_write(tp, 0xc8, ERIAR_MASK_1111, 0x00000002, ERIAR_EXGMAC);
5554 rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00000006, ERIAR_EXGMAC);
5555 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC);
5556 rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC);
5557 rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5558 rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
5559 rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0e00, 0xff00, ERIAR_EXGMAC);
Hayes Wang7e18dca2012-03-30 14:33:02 +08005560}
5561
Hayes Wang5598bfe2012-07-02 17:23:21 +08005562static void rtl_hw_start_8106(struct rtl8169_private *tp)
5563{
5564 void __iomem *ioaddr = tp->mmio_addr;
5565
5566 /* Force LAN exit from ASPM if Rx/Tx are not idle */
5567 RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800);
5568
Francois Romieu4521e1a92012-11-01 16:46:28 +00005569 RTL_W32(MISC, (RTL_R32(MISC) | DISABLE_LAN_EN) & ~EARLY_TALLY_EN);
Hayes Wang5598bfe2012-07-02 17:23:21 +08005570 RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET);
5571 RTL_W8(DLLPR, RTL_R8(DLLPR) & ~PFM_EN);
5572}
5573
Francois Romieu07ce4062007-02-23 23:36:39 +01005574static void rtl_hw_start_8101(struct net_device *dev)
5575{
Francois Romieucdf1a602007-06-11 23:29:50 +02005576 struct rtl8169_private *tp = netdev_priv(dev);
5577 void __iomem *ioaddr = tp->mmio_addr;
5578 struct pci_dev *pdev = tp->pci_dev;
5579
Francois Romieuda78dbf2012-01-26 14:18:23 +01005580 if (tp->mac_version >= RTL_GIGA_MAC_VER_30)
5581 tp->event_slow &= ~RxFIFOOver;
françois romieu811fd302011-12-04 20:30:45 +00005582
Francois Romieucecb5fd2011-04-01 10:21:07 +02005583 if (tp->mac_version == RTL_GIGA_MAC_VER_13 ||
Jiang Liu7d7903b2012-07-24 17:20:16 +08005584 tp->mac_version == RTL_GIGA_MAC_VER_16)
Bjorn Helgaas8200bc72012-08-22 10:29:42 -06005585 pcie_capability_set_word(pdev, PCI_EXP_DEVCTL,
5586 PCI_EXP_DEVCTL_NOSNOOP_EN);
Francois Romieucdf1a602007-06-11 23:29:50 +02005587
Hayes Wangd24e9aa2011-02-22 17:26:19 +08005588 RTL_W8(Cfg9346, Cfg9346_Unlock);
5589
hayeswang1a964642013-04-01 22:23:41 +00005590 RTL_W8(MaxTxPacketSize, TxPacketMax);
5591
5592 rtl_set_rx_max_size(ioaddr, rx_buf_sz);
5593
5594 tp->cp_cmd &= ~R810X_CPCMD_QUIRK_MASK;
5595 RTL_W16(CPlusCmd, tp->cp_cmd);
5596
5597 rtl_set_rx_tx_desc_registers(tp, ioaddr);
5598
5599 rtl_set_rx_tx_config_registers(tp);
5600
Francois Romieu2857ffb2008-08-02 21:08:49 +02005601 switch (tp->mac_version) {
5602 case RTL_GIGA_MAC_VER_07:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005603 rtl_hw_start_8102e_1(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005604 break;
5605
5606 case RTL_GIGA_MAC_VER_08:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005607 rtl_hw_start_8102e_3(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005608 break;
5609
5610 case RTL_GIGA_MAC_VER_09:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005611 rtl_hw_start_8102e_2(tp);
Francois Romieu2857ffb2008-08-02 21:08:49 +02005612 break;
Hayes Wang5a5e4442011-02-22 17:26:21 +08005613
5614 case RTL_GIGA_MAC_VER_29:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005615 rtl_hw_start_8105e_1(tp);
Hayes Wang5a5e4442011-02-22 17:26:21 +08005616 break;
5617 case RTL_GIGA_MAC_VER_30:
Hayes Wangbeb1fe12012-03-30 14:33:01 +08005618 rtl_hw_start_8105e_2(tp);
Hayes Wang5a5e4442011-02-22 17:26:21 +08005619 break;
Hayes Wang7e18dca2012-03-30 14:33:02 +08005620
5621 case RTL_GIGA_MAC_VER_37:
5622 rtl_hw_start_8402(tp);
5623 break;
Hayes Wang5598bfe2012-07-02 17:23:21 +08005624
5625 case RTL_GIGA_MAC_VER_39:
5626 rtl_hw_start_8106(tp);
5627 break;
hayeswang58152cd2013-04-01 22:23:42 +00005628 case RTL_GIGA_MAC_VER_43:
5629 rtl_hw_start_8168g_2(tp);
5630 break;
Francois Romieucdf1a602007-06-11 23:29:50 +02005631 }
5632
Hayes Wangd24e9aa2011-02-22 17:26:19 +08005633 RTL_W8(Cfg9346, Cfg9346_Lock);
Francois Romieucdf1a602007-06-11 23:29:50 +02005634
Francois Romieucdf1a602007-06-11 23:29:50 +02005635 RTL_W16(IntrMitigate, 0x0000);
5636
Francois Romieucdf1a602007-06-11 23:29:50 +02005637 RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
Francois Romieucdf1a602007-06-11 23:29:50 +02005638
Francois Romieucdf1a602007-06-11 23:29:50 +02005639 rtl_set_rx_mode(dev);
5640
hayeswang1a964642013-04-01 22:23:41 +00005641 RTL_R8(IntrMask);
5642
Francois Romieucdf1a602007-06-11 23:29:50 +02005643 RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005644}
5645
5646static int rtl8169_change_mtu(struct net_device *dev, int new_mtu)
5647{
Francois Romieud58d46b2011-05-03 16:38:29 +02005648 struct rtl8169_private *tp = netdev_priv(dev);
5649
5650 if (new_mtu < ETH_ZLEN ||
5651 new_mtu > rtl_chip_infos[tp->mac_version].jumbo_max)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005652 return -EINVAL;
5653
Francois Romieud58d46b2011-05-03 16:38:29 +02005654 if (new_mtu > ETH_DATA_LEN)
5655 rtl_hw_jumbo_enable(tp);
5656 else
5657 rtl_hw_jumbo_disable(tp);
5658
Linus Torvalds1da177e2005-04-16 15:20:36 -07005659 dev->mtu = new_mtu;
Michał Mirosław350fb322011-04-08 06:35:56 +00005660 netdev_update_features(dev);
5661
Stanislaw Gruszka323bb682010-10-20 22:25:41 +00005662 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005663}
5664
5665static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc)
5666{
Al Viro95e09182007-12-22 18:55:39 +00005667 desc->addr = cpu_to_le64(0x0badbadbadbadbadull);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005668 desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask);
5669}
5670
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005671static void rtl8169_free_rx_databuff(struct rtl8169_private *tp,
5672 void **data_buff, struct RxDesc *desc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005673{
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005674 dma_unmap_single(&tp->pci_dev->dev, le64_to_cpu(desc->addr), rx_buf_sz,
Stanislaw Gruszka231aee62010-10-20 22:25:38 +00005675 DMA_FROM_DEVICE);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005676
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005677 kfree(*data_buff);
5678 *data_buff = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005679 rtl8169_make_unusable_by_asic(desc);
5680}
5681
5682static inline void rtl8169_mark_to_asic(struct RxDesc *desc, u32 rx_buf_sz)
5683{
5684 u32 eor = le32_to_cpu(desc->opts1) & RingEnd;
5685
5686 desc->opts1 = cpu_to_le32(DescOwn | eor | rx_buf_sz);
5687}
5688
5689static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping,
5690 u32 rx_buf_sz)
5691{
5692 desc->addr = cpu_to_le64(mapping);
5693 wmb();
5694 rtl8169_mark_to_asic(desc, rx_buf_sz);
5695}
5696
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005697static inline void *rtl8169_align(void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005698{
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005699 return (void *)ALIGN((long)data, 16);
5700}
5701
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005702static struct sk_buff *rtl8169_alloc_rx_data(struct rtl8169_private *tp,
5703 struct RxDesc *desc)
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005704{
5705 void *data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005706 dma_addr_t mapping;
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005707 struct device *d = &tp->pci_dev->dev;
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005708 struct net_device *dev = tp->dev;
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005709 int node = dev->dev.parent ? dev_to_node(dev->dev.parent) : -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005710
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005711 data = kmalloc_node(rx_buf_sz, GFP_KERNEL, node);
5712 if (!data)
5713 return NULL;
Francois Romieue9f63f32007-02-28 23:16:57 +01005714
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005715 if (rtl8169_align(data) != data) {
5716 kfree(data);
5717 data = kmalloc_node(rx_buf_sz + 15, GFP_KERNEL, node);
5718 if (!data)
5719 return NULL;
5720 }
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005721
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005722 mapping = dma_map_single(d, rtl8169_align(data), rx_buf_sz,
Stanislaw Gruszka231aee62010-10-20 22:25:38 +00005723 DMA_FROM_DEVICE);
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005724 if (unlikely(dma_mapping_error(d, mapping))) {
5725 if (net_ratelimit())
5726 netif_err(tp, drv, tp->dev, "Failed to map RX DMA!\n");
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005727 goto err_out;
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005728 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005729
5730 rtl8169_map_to_asic(desc, mapping, rx_buf_sz);
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005731 return data;
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005732
5733err_out:
5734 kfree(data);
5735 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005736}
5737
5738static void rtl8169_rx_clear(struct rtl8169_private *tp)
5739{
Francois Romieu07d3f512007-02-21 22:40:46 +01005740 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005741
5742 for (i = 0; i < NUM_RX_DESC; i++) {
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005743 if (tp->Rx_databuff[i]) {
5744 rtl8169_free_rx_databuff(tp, tp->Rx_databuff + i,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005745 tp->RxDescArray + i);
5746 }
5747 }
5748}
5749
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005750static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005751{
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005752 desc->opts1 |= cpu_to_le32(RingEnd);
5753}
Francois Romieu5b0384f2006-08-16 16:00:01 +02005754
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005755static int rtl8169_rx_fill(struct rtl8169_private *tp)
5756{
5757 unsigned int i;
5758
5759 for (i = 0; i < NUM_RX_DESC; i++) {
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005760 void *data;
Francois Romieu4ae47c22007-06-16 23:28:45 +02005761
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005762 if (tp->Rx_databuff[i])
Linus Torvalds1da177e2005-04-16 15:20:36 -07005763 continue;
Francois Romieubcf0bf92006-07-26 23:14:13 +02005764
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005765 data = rtl8169_alloc_rx_data(tp, tp->RxDescArray + i);
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005766 if (!data) {
5767 rtl8169_make_unusable_by_asic(tp->RxDescArray + i);
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005768 goto err_out;
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005769 }
5770 tp->Rx_databuff[i] = data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005771 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005772
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005773 rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1);
5774 return 0;
5775
5776err_out:
5777 rtl8169_rx_clear(tp);
5778 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005779}
5780
Linus Torvalds1da177e2005-04-16 15:20:36 -07005781static int rtl8169_init_ring(struct net_device *dev)
5782{
5783 struct rtl8169_private *tp = netdev_priv(dev);
5784
5785 rtl8169_init_ring_indexes(tp);
5786
5787 memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info));
Eric Dumazet6f0333b2010-10-11 11:17:47 +00005788 memset(tp->Rx_databuff, 0x0, NUM_RX_DESC * sizeof(void *));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005789
Stanislaw Gruszka0ecbe1c2010-10-20 22:25:37 +00005790 return rtl8169_rx_fill(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005791}
5792
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005793static void rtl8169_unmap_tx_skb(struct device *d, struct ring_info *tx_skb,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005794 struct TxDesc *desc)
5795{
5796 unsigned int len = tx_skb->len;
5797
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005798 dma_unmap_single(d, le64_to_cpu(desc->addr), len, DMA_TO_DEVICE);
5799
Linus Torvalds1da177e2005-04-16 15:20:36 -07005800 desc->opts1 = 0x00;
5801 desc->opts2 = 0x00;
5802 desc->addr = 0x00;
5803 tx_skb->len = 0;
5804}
5805
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005806static void rtl8169_tx_clear_range(struct rtl8169_private *tp, u32 start,
5807 unsigned int n)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005808{
5809 unsigned int i;
5810
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005811 for (i = 0; i < n; i++) {
5812 unsigned int entry = (start + i) % NUM_TX_DESC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005813 struct ring_info *tx_skb = tp->tx_skb + entry;
5814 unsigned int len = tx_skb->len;
5815
5816 if (len) {
5817 struct sk_buff *skb = tx_skb->skb;
5818
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005819 rtl8169_unmap_tx_skb(&tp->pci_dev->dev, tx_skb,
Linus Torvalds1da177e2005-04-16 15:20:36 -07005820 tp->TxDescArray + entry);
5821 if (skb) {
Stanislaw Gruszkacac4b222010-10-20 22:25:40 +00005822 tp->dev->stats.tx_dropped++;
Eric W. Biederman989c9ba2014-03-11 14:16:14 -07005823 dev_kfree_skb_any(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005824 tx_skb->skb = NULL;
5825 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005826 }
5827 }
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005828}
5829
5830static void rtl8169_tx_clear(struct rtl8169_private *tp)
5831{
5832 rtl8169_tx_clear_range(tp, tp->dirty_tx, NUM_TX_DESC);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005833 tp->cur_tx = tp->dirty_tx = 0;
5834}
5835
Francois Romieu4422bcd2012-01-26 11:23:32 +01005836static void rtl_reset_work(struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005837{
David Howellsc4028952006-11-22 14:57:56 +00005838 struct net_device *dev = tp->dev;
Francois Romieu56de4142011-03-15 17:29:31 +01005839 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005840
Francois Romieuda78dbf2012-01-26 14:18:23 +01005841 napi_disable(&tp->napi);
5842 netif_stop_queue(dev);
5843 synchronize_sched();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005844
françois romieuc7c2c392011-12-04 20:30:52 +00005845 rtl8169_hw_reset(tp);
5846
Francois Romieu56de4142011-03-15 17:29:31 +01005847 for (i = 0; i < NUM_RX_DESC; i++)
5848 rtl8169_mark_to_asic(tp->RxDescArray + i, rx_buf_sz);
5849
Linus Torvalds1da177e2005-04-16 15:20:36 -07005850 rtl8169_tx_clear(tp);
françois romieuc7c2c392011-12-04 20:30:52 +00005851 rtl8169_init_ring_indexes(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005852
Francois Romieuda78dbf2012-01-26 14:18:23 +01005853 napi_enable(&tp->napi);
Francois Romieu56de4142011-03-15 17:29:31 +01005854 rtl_hw_start(dev);
5855 netif_wake_queue(dev);
5856 rtl8169_check_link_status(dev, tp, tp->mmio_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005857}
5858
5859static void rtl8169_tx_timeout(struct net_device *dev)
5860{
Francois Romieuda78dbf2012-01-26 14:18:23 +01005861 struct rtl8169_private *tp = netdev_priv(dev);
5862
5863 rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005864}
5865
5866static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb,
Francois Romieu2b7b4312011-04-18 22:53:24 -07005867 u32 *opts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005868{
5869 struct skb_shared_info *info = skb_shinfo(skb);
5870 unsigned int cur_frag, entry;
Jeff Garzika6343af2007-07-17 05:39:58 -04005871 struct TxDesc * uninitialized_var(txd);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005872 struct device *d = &tp->pci_dev->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005873
5874 entry = tp->cur_tx;
5875 for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) {
Eric Dumazet9e903e02011-10-18 21:00:24 +00005876 const skb_frag_t *frag = info->frags + cur_frag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005877 dma_addr_t mapping;
5878 u32 status, len;
5879 void *addr;
5880
5881 entry = (entry + 1) % NUM_TX_DESC;
5882
5883 txd = tp->TxDescArray + entry;
Eric Dumazet9e903e02011-10-18 21:00:24 +00005884 len = skb_frag_size(frag);
Ian Campbell929f6182011-08-31 00:47:06 +00005885 addr = skb_frag_address(frag);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00005886 mapping = dma_map_single(d, addr, len, DMA_TO_DEVICE);
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005887 if (unlikely(dma_mapping_error(d, mapping))) {
5888 if (net_ratelimit())
5889 netif_err(tp, drv, tp->dev,
5890 "Failed to map TX fragments DMA!\n");
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005891 goto err_out;
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00005892 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005893
Francois Romieucecb5fd2011-04-01 10:21:07 +02005894 /* Anti gcc 2.95.3 bugware (sic) */
Francois Romieu2b7b4312011-04-18 22:53:24 -07005895 status = opts[0] | len |
5896 (RingEnd * !((entry + 1) % NUM_TX_DESC));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005897
5898 txd->opts1 = cpu_to_le32(status);
Francois Romieu2b7b4312011-04-18 22:53:24 -07005899 txd->opts2 = cpu_to_le32(opts[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005900 txd->addr = cpu_to_le64(mapping);
5901
5902 tp->tx_skb[entry].len = len;
5903 }
5904
5905 if (cur_frag) {
5906 tp->tx_skb[entry].skb = skb;
5907 txd->opts1 |= cpu_to_le32(LastFrag);
5908 }
5909
5910 return cur_frag;
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00005911
5912err_out:
5913 rtl8169_tx_clear_range(tp, tp->cur_tx + 1, cur_frag);
5914 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005915}
5916
françois romieub423e9a2013-05-18 01:24:46 +00005917static bool rtl_skb_pad(struct sk_buff *skb)
5918{
5919 if (skb_padto(skb, ETH_ZLEN))
5920 return false;
5921 skb_put(skb, ETH_ZLEN - skb->len);
5922 return true;
5923}
5924
5925static bool rtl_test_hw_pad_bug(struct rtl8169_private *tp, struct sk_buff *skb)
5926{
5927 return skb->len < ETH_ZLEN && tp->mac_version == RTL_GIGA_MAC_VER_34;
5928}
5929
hayeswange9746042014-07-11 16:25:58 +08005930static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
5931 struct net_device *dev);
5932/* r8169_csum_workaround()
5933 * The hw limites the value the transport offset. When the offset is out of the
5934 * range, calculate the checksum by sw.
5935 */
5936static void r8169_csum_workaround(struct rtl8169_private *tp,
5937 struct sk_buff *skb)
5938{
5939 if (skb_shinfo(skb)->gso_size) {
5940 netdev_features_t features = tp->dev->features;
5941 struct sk_buff *segs, *nskb;
5942
5943 features &= ~(NETIF_F_SG | NETIF_F_IPV6_CSUM | NETIF_F_TSO6);
5944 segs = skb_gso_segment(skb, features);
5945 if (IS_ERR(segs) || !segs)
5946 goto drop;
5947
5948 do {
5949 nskb = segs;
5950 segs = segs->next;
5951 nskb->next = NULL;
5952 rtl8169_start_xmit(nskb, tp->dev);
5953 } while (segs);
5954
5955 dev_kfree_skb(skb);
5956 } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
5957 if (skb_checksum_help(skb) < 0)
5958 goto drop;
5959
5960 rtl8169_start_xmit(skb, tp->dev);
5961 } else {
5962 struct net_device_stats *stats;
5963
5964drop:
5965 stats = &tp->dev->stats;
5966 stats->tx_dropped++;
5967 dev_kfree_skb(skb);
5968 }
5969}
5970
5971/* msdn_giant_send_check()
5972 * According to the document of microsoft, the TCP Pseudo Header excludes the
5973 * packet length for IPv6 TCP large packets.
5974 */
5975static int msdn_giant_send_check(struct sk_buff *skb)
5976{
5977 const struct ipv6hdr *ipv6h;
5978 struct tcphdr *th;
5979 int ret;
5980
5981 ret = skb_cow_head(skb, 0);
5982 if (ret)
5983 return ret;
5984
5985 ipv6h = ipv6_hdr(skb);
5986 th = tcp_hdr(skb);
5987
5988 th->check = 0;
5989 th->check = ~tcp_v6_check(0, &ipv6h->saddr, &ipv6h->daddr, 0);
5990
5991 return ret;
5992}
5993
5994static inline __be16 get_protocol(struct sk_buff *skb)
5995{
5996 __be16 protocol;
5997
5998 if (skb->protocol == htons(ETH_P_8021Q))
5999 protocol = vlan_eth_hdr(skb)->h_vlan_encapsulated_proto;
6000 else
6001 protocol = skb->protocol;
6002
6003 return protocol;
6004}
6005
hayeswang5888d3f2014-07-11 16:25:56 +08006006static bool rtl8169_tso_csum_v1(struct rtl8169_private *tp,
6007 struct sk_buff *skb, u32 *opts)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006008{
Michał Mirosław350fb322011-04-08 06:35:56 +00006009 u32 mss = skb_shinfo(skb)->gso_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006010
Francois Romieu2b7b4312011-04-18 22:53:24 -07006011 if (mss) {
6012 opts[0] |= TD_LSO;
hayeswang5888d3f2014-07-11 16:25:56 +08006013 opts[0] |= min(mss, TD_MSS_MAX) << TD0_MSS_SHIFT;
6014 } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
6015 const struct iphdr *ip = ip_hdr(skb);
6016
6017 if (ip->protocol == IPPROTO_TCP)
6018 opts[0] |= TD0_IP_CS | TD0_TCP_CS;
6019 else if (ip->protocol == IPPROTO_UDP)
6020 opts[0] |= TD0_IP_CS | TD0_UDP_CS;
6021 else
6022 WARN_ON_ONCE(1);
6023 }
6024
6025 return true;
6026}
6027
6028static bool rtl8169_tso_csum_v2(struct rtl8169_private *tp,
6029 struct sk_buff *skb, u32 *opts)
6030{
hayeswangbdfa4ed2014-07-11 16:25:57 +08006031 u32 transport_offset = (u32)skb_transport_offset(skb);
hayeswang5888d3f2014-07-11 16:25:56 +08006032 u32 mss = skb_shinfo(skb)->gso_size;
6033
6034 if (mss) {
hayeswange9746042014-07-11 16:25:58 +08006035 if (transport_offset > GTTCPHO_MAX) {
6036 netif_warn(tp, tx_err, tp->dev,
6037 "Invalid transport offset 0x%x for TSO\n",
6038 transport_offset);
6039 return false;
6040 }
6041
6042 switch (get_protocol(skb)) {
6043 case htons(ETH_P_IP):
6044 opts[0] |= TD1_GTSENV4;
6045 break;
6046
6047 case htons(ETH_P_IPV6):
6048 if (msdn_giant_send_check(skb))
6049 return false;
6050
6051 opts[0] |= TD1_GTSENV6;
6052 break;
6053
6054 default:
6055 WARN_ON_ONCE(1);
6056 break;
6057 }
6058
hayeswangbdfa4ed2014-07-11 16:25:57 +08006059 opts[0] |= transport_offset << GTTCPHO_SHIFT;
hayeswang5888d3f2014-07-11 16:25:56 +08006060 opts[1] |= min(mss, TD_MSS_MAX) << TD1_MSS_SHIFT;
Francois Romieu2b7b4312011-04-18 22:53:24 -07006061 } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
hayeswange9746042014-07-11 16:25:58 +08006062 u8 ip_protocol;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006063
françois romieub423e9a2013-05-18 01:24:46 +00006064 if (unlikely(rtl_test_hw_pad_bug(tp, skb)))
6065 return skb_checksum_help(skb) == 0 && rtl_skb_pad(skb);
6066
hayeswange9746042014-07-11 16:25:58 +08006067 if (transport_offset > TCPHO_MAX) {
6068 netif_warn(tp, tx_err, tp->dev,
6069 "Invalid transport offset 0x%x\n",
6070 transport_offset);
6071 return false;
6072 }
6073
6074 switch (get_protocol(skb)) {
6075 case htons(ETH_P_IP):
6076 opts[1] |= TD1_IPv4_CS;
6077 ip_protocol = ip_hdr(skb)->protocol;
6078 break;
6079
6080 case htons(ETH_P_IPV6):
6081 opts[1] |= TD1_IPv6_CS;
6082 ip_protocol = ipv6_hdr(skb)->nexthdr;
6083 break;
6084
6085 default:
6086 ip_protocol = IPPROTO_RAW;
6087 break;
6088 }
6089
6090 if (ip_protocol == IPPROTO_TCP)
6091 opts[1] |= TD1_TCP_CS;
6092 else if (ip_protocol == IPPROTO_UDP)
6093 opts[1] |= TD1_UDP_CS;
Francois Romieu2b7b4312011-04-18 22:53:24 -07006094 else
6095 WARN_ON_ONCE(1);
hayeswange9746042014-07-11 16:25:58 +08006096
6097 opts[1] |= transport_offset << TCPHO_SHIFT;
françois romieub423e9a2013-05-18 01:24:46 +00006098 } else {
6099 if (unlikely(rtl_test_hw_pad_bug(tp, skb)))
6100 return rtl_skb_pad(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006101 }
hayeswang5888d3f2014-07-11 16:25:56 +08006102
françois romieub423e9a2013-05-18 01:24:46 +00006103 return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006104}
6105
Stephen Hemminger613573252009-08-31 19:50:58 +00006106static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
6107 struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006108{
6109 struct rtl8169_private *tp = netdev_priv(dev);
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00006110 unsigned int entry = tp->cur_tx % NUM_TX_DESC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006111 struct TxDesc *txd = tp->TxDescArray + entry;
6112 void __iomem *ioaddr = tp->mmio_addr;
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00006113 struct device *d = &tp->pci_dev->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006114 dma_addr_t mapping;
6115 u32 status, len;
Francois Romieu2b7b4312011-04-18 22:53:24 -07006116 u32 opts[2];
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00006117 int frags;
Francois Romieu5b0384f2006-08-16 16:00:01 +02006118
Julien Ducourthial477206a2012-05-09 00:00:06 +02006119 if (unlikely(!TX_FRAGS_READY_FOR(tp, skb_shinfo(skb)->nr_frags))) {
Joe Perchesbf82c182010-02-09 11:49:50 +00006120 netif_err(tp, drv, dev, "BUG! Tx Ring full when queue awake!\n");
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00006121 goto err_stop_0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006122 }
6123
6124 if (unlikely(le32_to_cpu(txd->opts1) & DescOwn))
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00006125 goto err_stop_0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006126
françois romieub423e9a2013-05-18 01:24:46 +00006127 opts[1] = cpu_to_le32(rtl8169_tx_vlan_tag(skb));
6128 opts[0] = DescOwn;
6129
hayeswange9746042014-07-11 16:25:58 +08006130 if (!tp->tso_csum(tp, skb, opts)) {
6131 r8169_csum_workaround(tp, skb);
6132 return NETDEV_TX_OK;
6133 }
françois romieub423e9a2013-05-18 01:24:46 +00006134
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00006135 len = skb_headlen(skb);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00006136 mapping = dma_map_single(d, skb->data, len, DMA_TO_DEVICE);
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00006137 if (unlikely(dma_mapping_error(d, mapping))) {
6138 if (net_ratelimit())
6139 netif_err(tp, drv, dev, "Failed to map TX DMA!\n");
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00006140 goto err_dma_0;
Stanislaw Gruszkad827d862010-10-20 22:25:43 +00006141 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006142
6143 tp->tx_skb[entry].len = len;
6144 txd->addr = cpu_to_le64(mapping);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006145
Francois Romieu2b7b4312011-04-18 22:53:24 -07006146 frags = rtl8169_xmit_frags(tp, skb, opts);
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00006147 if (frags < 0)
6148 goto err_dma_1;
6149 else if (frags)
Francois Romieu2b7b4312011-04-18 22:53:24 -07006150 opts[0] |= FirstFrag;
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00006151 else {
Francois Romieu2b7b4312011-04-18 22:53:24 -07006152 opts[0] |= FirstFrag | LastFrag;
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00006153 tp->tx_skb[entry].skb = skb;
6154 }
6155
Francois Romieu2b7b4312011-04-18 22:53:24 -07006156 txd->opts2 = cpu_to_le32(opts[1]);
6157
Richard Cochran5047fb52012-03-10 07:29:42 +00006158 skb_tx_timestamp(skb);
6159
Linus Torvalds1da177e2005-04-16 15:20:36 -07006160 wmb();
6161
Francois Romieucecb5fd2011-04-01 10:21:07 +02006162 /* Anti gcc 2.95.3 bugware (sic) */
Francois Romieu2b7b4312011-04-18 22:53:24 -07006163 status = opts[0] | len | (RingEnd * !((entry + 1) % NUM_TX_DESC));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006164 txd->opts1 = cpu_to_le32(status);
6165
Linus Torvalds1da177e2005-04-16 15:20:36 -07006166 tp->cur_tx += frags + 1;
6167
David Dillow4c020a92010-03-03 16:33:10 +00006168 wmb();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006169
Francois Romieucecb5fd2011-04-01 10:21:07 +02006170 RTL_W8(TxPoll, NPQ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006171
Francois Romieuda78dbf2012-01-26 14:18:23 +01006172 mmiowb();
6173
Julien Ducourthial477206a2012-05-09 00:00:06 +02006174 if (!TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS)) {
Francois Romieuae1f23f2012-01-31 00:00:19 +01006175 /* Avoid wrongly optimistic queue wake-up: rtl_tx thread must
6176 * not miss a ring update when it notices a stopped queue.
6177 */
6178 smp_wmb();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006179 netif_stop_queue(dev);
Francois Romieuae1f23f2012-01-31 00:00:19 +01006180 /* Sync with rtl_tx:
6181 * - publish queue status and cur_tx ring index (write barrier)
6182 * - refresh dirty_tx ring index (read barrier).
6183 * May the current thread have a pessimistic view of the ring
6184 * status and forget to wake up queue, a racing rtl_tx thread
6185 * can't.
6186 */
Francois Romieu1e874e02012-01-27 15:05:38 +01006187 smp_mb();
Julien Ducourthial477206a2012-05-09 00:00:06 +02006188 if (TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS))
Linus Torvalds1da177e2005-04-16 15:20:36 -07006189 netif_wake_queue(dev);
6190 }
6191
Stephen Hemminger613573252009-08-31 19:50:58 +00006192 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006193
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00006194err_dma_1:
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00006195 rtl8169_unmap_tx_skb(d, tp->tx_skb + entry, txd);
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00006196err_dma_0:
Eric W. Biederman989c9ba2014-03-11 14:16:14 -07006197 dev_kfree_skb_any(skb);
Stanislaw Gruszka3eafe502010-10-20 22:25:36 +00006198 dev->stats.tx_dropped++;
6199 return NETDEV_TX_OK;
6200
6201err_stop_0:
Linus Torvalds1da177e2005-04-16 15:20:36 -07006202 netif_stop_queue(dev);
Francois Romieucebf8cc2007-10-18 12:06:54 +02006203 dev->stats.tx_dropped++;
Stephen Hemminger613573252009-08-31 19:50:58 +00006204 return NETDEV_TX_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006205}
6206
6207static void rtl8169_pcierr_interrupt(struct net_device *dev)
6208{
6209 struct rtl8169_private *tp = netdev_priv(dev);
6210 struct pci_dev *pdev = tp->pci_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006211 u16 pci_status, pci_cmd;
6212
6213 pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd);
6214 pci_read_config_word(pdev, PCI_STATUS, &pci_status);
6215
Joe Perchesbf82c182010-02-09 11:49:50 +00006216 netif_err(tp, intr, dev, "PCI error (cmd = 0x%04x, status = 0x%04x)\n",
6217 pci_cmd, pci_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006218
6219 /*
6220 * The recovery sequence below admits a very elaborated explanation:
6221 * - it seems to work;
Francois Romieud03902b2006-11-23 00:00:42 +01006222 * - I did not see what else could be done;
6223 * - it makes iop3xx happy.
Linus Torvalds1da177e2005-04-16 15:20:36 -07006224 *
6225 * Feel free to adjust to your needs.
6226 */
Francois Romieua27993f2006-12-18 00:04:19 +01006227 if (pdev->broken_parity_status)
Francois Romieud03902b2006-11-23 00:00:42 +01006228 pci_cmd &= ~PCI_COMMAND_PARITY;
6229 else
6230 pci_cmd |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY;
6231
6232 pci_write_config_word(pdev, PCI_COMMAND, pci_cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006233
6234 pci_write_config_word(pdev, PCI_STATUS,
6235 pci_status & (PCI_STATUS_DETECTED_PARITY |
6236 PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_REC_MASTER_ABORT |
6237 PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_SIG_TARGET_ABORT));
6238
6239 /* The infamous DAC f*ckup only happens at boot time */
Timo Teräs9fba0812013-01-15 21:01:24 +00006240 if ((tp->cp_cmd & PCIDAC) && !tp->cur_rx) {
françois romieue6de30d2011-01-03 15:08:37 +00006241 void __iomem *ioaddr = tp->mmio_addr;
6242
Joe Perchesbf82c182010-02-09 11:49:50 +00006243 netif_info(tp, intr, dev, "disabling PCI DAC\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07006244 tp->cp_cmd &= ~PCIDAC;
6245 RTL_W16(CPlusCmd, tp->cp_cmd);
6246 dev->features &= ~NETIF_F_HIGHDMA;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006247 }
6248
françois romieue6de30d2011-01-03 15:08:37 +00006249 rtl8169_hw_reset(tp);
Francois Romieud03902b2006-11-23 00:00:42 +01006250
Francois Romieu98ddf982012-01-31 10:47:34 +01006251 rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006252}
6253
Francois Romieuda78dbf2012-01-26 14:18:23 +01006254static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006255{
6256 unsigned int dirty_tx, tx_left;
6257
Linus Torvalds1da177e2005-04-16 15:20:36 -07006258 dirty_tx = tp->dirty_tx;
6259 smp_rmb();
6260 tx_left = tp->cur_tx - dirty_tx;
6261
6262 while (tx_left > 0) {
6263 unsigned int entry = dirty_tx % NUM_TX_DESC;
6264 struct ring_info *tx_skb = tp->tx_skb + entry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006265 u32 status;
6266
6267 rmb();
6268 status = le32_to_cpu(tp->TxDescArray[entry].opts1);
6269 if (status & DescOwn)
6270 break;
6271
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00006272 rtl8169_unmap_tx_skb(&tp->pci_dev->dev, tx_skb,
6273 tp->TxDescArray + entry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006274 if (status & LastFrag) {
Francois Romieu17bcb682012-07-23 22:55:55 +02006275 u64_stats_update_begin(&tp->tx_stats.syncp);
6276 tp->tx_stats.packets++;
6277 tp->tx_stats.bytes += tx_skb->skb->len;
6278 u64_stats_update_end(&tp->tx_stats.syncp);
Eric W. Biederman989c9ba2014-03-11 14:16:14 -07006279 dev_kfree_skb_any(tx_skb->skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006280 tx_skb->skb = NULL;
6281 }
6282 dirty_tx++;
6283 tx_left--;
6284 }
6285
6286 if (tp->dirty_tx != dirty_tx) {
6287 tp->dirty_tx = dirty_tx;
Francois Romieuae1f23f2012-01-31 00:00:19 +01006288 /* Sync with rtl8169_start_xmit:
6289 * - publish dirty_tx ring index (write barrier)
6290 * - refresh cur_tx ring index and queue status (read barrier)
6291 * May the current thread miss the stopped queue condition,
6292 * a racing xmit thread can only have a right view of the
6293 * ring status.
6294 */
Francois Romieu1e874e02012-01-27 15:05:38 +01006295 smp_mb();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006296 if (netif_queue_stopped(dev) &&
Julien Ducourthial477206a2012-05-09 00:00:06 +02006297 TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006298 netif_wake_queue(dev);
6299 }
Francois Romieud78ae2d2007-08-26 20:08:19 +02006300 /*
6301 * 8168 hack: TxPoll requests are lost when the Tx packets are
6302 * too close. Let's kick an extra TxPoll request when a burst
6303 * of start_xmit activity is detected (if it is not detected,
6304 * it is slow enough). -- FR
6305 */
Francois Romieuda78dbf2012-01-26 14:18:23 +01006306 if (tp->cur_tx != dirty_tx) {
6307 void __iomem *ioaddr = tp->mmio_addr;
6308
Francois Romieud78ae2d2007-08-26 20:08:19 +02006309 RTL_W8(TxPoll, NPQ);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006310 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006311 }
6312}
6313
Francois Romieu126fa4b2005-05-12 20:09:17 -04006314static inline int rtl8169_fragmented_frame(u32 status)
6315{
6316 return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag);
6317}
6318
Eric Dumazetadea1ac72010-09-05 20:04:05 -07006319static inline void rtl8169_rx_csum(struct sk_buff *skb, u32 opts1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006320{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006321 u32 status = opts1 & RxProtoMask;
6322
6323 if (((status == RxProtoTCP) && !(opts1 & TCPFail)) ||
Shan Weid5d3ebe2010-11-12 00:15:25 +00006324 ((status == RxProtoUDP) && !(opts1 & UDPFail)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07006325 skb->ip_summed = CHECKSUM_UNNECESSARY;
6326 else
Eric Dumazetbc8acf22010-09-02 13:07:41 -07006327 skb_checksum_none_assert(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006328}
6329
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006330static struct sk_buff *rtl8169_try_rx_copy(void *data,
6331 struct rtl8169_private *tp,
6332 int pkt_size,
6333 dma_addr_t addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006334{
Stephen Hemmingerb4496552007-06-17 01:06:49 +02006335 struct sk_buff *skb;
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00006336 struct device *d = &tp->pci_dev->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006337
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006338 data = rtl8169_align(data);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00006339 dma_sync_single_for_cpu(d, addr, pkt_size, DMA_FROM_DEVICE);
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006340 prefetch(data);
6341 skb = netdev_alloc_skb_ip_align(tp->dev, pkt_size);
6342 if (skb)
6343 memcpy(skb->data, data, pkt_size);
Stanislaw Gruszka48addcc2010-10-20 22:25:39 +00006344 dma_sync_single_for_device(d, addr, pkt_size, DMA_FROM_DEVICE);
6345
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006346 return skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006347}
6348
Francois Romieuda78dbf2012-01-26 14:18:23 +01006349static int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, u32 budget)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006350{
6351 unsigned int cur_rx, rx_left;
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006352 unsigned int count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006353
Linus Torvalds1da177e2005-04-16 15:20:36 -07006354 cur_rx = tp->cur_rx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006355
Timo Teräs9fba0812013-01-15 21:01:24 +00006356 for (rx_left = min(budget, NUM_RX_DESC); rx_left > 0; rx_left--, cur_rx++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006357 unsigned int entry = cur_rx % NUM_RX_DESC;
Francois Romieu126fa4b2005-05-12 20:09:17 -04006358 struct RxDesc *desc = tp->RxDescArray + entry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006359 u32 status;
6360
6361 rmb();
David S. Miller8decf862011-09-22 03:23:13 -04006362 status = le32_to_cpu(desc->opts1) & tp->opts1_mask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006363
6364 if (status & DescOwn)
6365 break;
Richard Dawe4dcb7d32005-05-27 21:12:00 +02006366 if (unlikely(status & RxRES)) {
Joe Perchesbf82c182010-02-09 11:49:50 +00006367 netif_info(tp, rx_err, dev, "Rx ERROR. status = %08x\n",
6368 status);
Francois Romieucebf8cc2007-10-18 12:06:54 +02006369 dev->stats.rx_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006370 if (status & (RxRWT | RxRUNT))
Francois Romieucebf8cc2007-10-18 12:06:54 +02006371 dev->stats.rx_length_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006372 if (status & RxCRC)
Francois Romieucebf8cc2007-10-18 12:06:54 +02006373 dev->stats.rx_crc_errors++;
Francois Romieu9dccf612006-05-14 12:31:17 +02006374 if (status & RxFOVF) {
Francois Romieuda78dbf2012-01-26 14:18:23 +01006375 rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
Francois Romieucebf8cc2007-10-18 12:06:54 +02006376 dev->stats.rx_fifo_errors++;
Francois Romieu9dccf612006-05-14 12:31:17 +02006377 }
Ben Greear6bbe0212012-02-10 15:04:33 +00006378 if ((status & (RxRUNT | RxCRC)) &&
6379 !(status & (RxRWT | RxFOVF)) &&
6380 (dev->features & NETIF_F_RXALL))
6381 goto process_pkt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006382 } else {
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006383 struct sk_buff *skb;
Ben Greear6bbe0212012-02-10 15:04:33 +00006384 dma_addr_t addr;
6385 int pkt_size;
6386
6387process_pkt:
6388 addr = le64_to_cpu(desc->addr);
Ben Greear79d0c1d2012-02-10 15:04:34 +00006389 if (likely(!(dev->features & NETIF_F_RXFCS)))
6390 pkt_size = (status & 0x00003fff) - 4;
6391 else
6392 pkt_size = status & 0x00003fff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006393
Francois Romieu126fa4b2005-05-12 20:09:17 -04006394 /*
6395 * The driver does not support incoming fragmented
6396 * frames. They are seen as a symptom of over-mtu
6397 * sized frames.
6398 */
6399 if (unlikely(rtl8169_fragmented_frame(status))) {
Francois Romieucebf8cc2007-10-18 12:06:54 +02006400 dev->stats.rx_dropped++;
6401 dev->stats.rx_length_errors++;
françois romieuce11ff52013-01-24 13:30:06 +00006402 goto release_descriptor;
Francois Romieu126fa4b2005-05-12 20:09:17 -04006403 }
6404
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006405 skb = rtl8169_try_rx_copy(tp->Rx_databuff[entry],
6406 tp, pkt_size, addr);
Eric Dumazet6f0333b2010-10-11 11:17:47 +00006407 if (!skb) {
6408 dev->stats.rx_dropped++;
françois romieuce11ff52013-01-24 13:30:06 +00006409 goto release_descriptor;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006410 }
6411
Eric Dumazetadea1ac72010-09-05 20:04:05 -07006412 rtl8169_rx_csum(skb, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006413 skb_put(skb, pkt_size);
6414 skb->protocol = eth_type_trans(skb, dev);
6415
Francois Romieu7a8fc772011-03-01 17:18:33 +01006416 rtl8169_rx_vlan_tag(desc, skb);
6417
Francois Romieu56de4142011-03-15 17:29:31 +01006418 napi_gro_receive(&tp->napi, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006419
Junchang Wang8027aa22012-03-04 23:30:32 +01006420 u64_stats_update_begin(&tp->rx_stats.syncp);
6421 tp->rx_stats.packets++;
6422 tp->rx_stats.bytes += pkt_size;
6423 u64_stats_update_end(&tp->rx_stats.syncp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006424 }
françois romieuce11ff52013-01-24 13:30:06 +00006425release_descriptor:
6426 desc->opts2 = 0;
6427 wmb();
6428 rtl8169_mark_to_asic(desc, rx_buf_sz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006429 }
6430
6431 count = cur_rx - tp->cur_rx;
6432 tp->cur_rx = cur_rx;
6433
Linus Torvalds1da177e2005-04-16 15:20:36 -07006434 return count;
6435}
6436
Francois Romieu07d3f512007-02-21 22:40:46 +01006437static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006438{
Francois Romieu07d3f512007-02-21 22:40:46 +01006439 struct net_device *dev = dev_instance;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006440 struct rtl8169_private *tp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006441 int handled = 0;
Francois Romieu9085cdfa2012-01-26 12:59:08 +01006442 u16 status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006443
Francois Romieu9085cdfa2012-01-26 12:59:08 +01006444 status = rtl_get_events(tp);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006445 if (status && status != 0xffff) {
6446 status &= RTL_EVENT_NAPI | tp->event_slow;
6447 if (status) {
6448 handled = 1;
françois romieu811fd302011-12-04 20:30:45 +00006449
Francois Romieuda78dbf2012-01-26 14:18:23 +01006450 rtl_irq_disable(tp);
6451 napi_schedule(&tp->napi);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006452 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006453 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006454 return IRQ_RETVAL(handled);
6455}
6456
Francois Romieuda78dbf2012-01-26 14:18:23 +01006457/*
6458 * Workqueue context.
6459 */
6460static void rtl_slow_event_work(struct rtl8169_private *tp)
6461{
6462 struct net_device *dev = tp->dev;
6463 u16 status;
6464
6465 status = rtl_get_events(tp) & tp->event_slow;
6466 rtl_ack_events(tp, status);
6467
6468 if (unlikely(status & RxFIFOOver)) {
6469 switch (tp->mac_version) {
6470 /* Work around for rx fifo overflow */
6471 case RTL_GIGA_MAC_VER_11:
6472 netif_stop_queue(dev);
Francois Romieu934714d2012-01-31 11:09:21 +01006473 /* XXX - Hack alert. See rtl_task(). */
6474 set_bit(RTL_FLAG_TASK_RESET_PENDING, tp->wk.flags);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006475 default:
6476 break;
6477 }
6478 }
6479
6480 if (unlikely(status & SYSErr))
6481 rtl8169_pcierr_interrupt(dev);
6482
6483 if (status & LinkChg)
6484 __rtl8169_check_link_status(dev, tp, tp->mmio_addr, true);
6485
françois romieu7dbb4912012-06-09 10:53:16 +00006486 rtl_irq_enable_all(tp);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006487}
6488
Francois Romieu4422bcd2012-01-26 11:23:32 +01006489static void rtl_task(struct work_struct *work)
6490{
Francois Romieuda78dbf2012-01-26 14:18:23 +01006491 static const struct {
6492 int bitnr;
6493 void (*action)(struct rtl8169_private *);
6494 } rtl_work[] = {
Francois Romieu934714d2012-01-31 11:09:21 +01006495 /* XXX - keep rtl_slow_event_work() as first element. */
Francois Romieuda78dbf2012-01-26 14:18:23 +01006496 { RTL_FLAG_TASK_SLOW_PENDING, rtl_slow_event_work },
6497 { RTL_FLAG_TASK_RESET_PENDING, rtl_reset_work },
6498 { RTL_FLAG_TASK_PHY_PENDING, rtl_phy_work }
6499 };
Francois Romieu4422bcd2012-01-26 11:23:32 +01006500 struct rtl8169_private *tp =
6501 container_of(work, struct rtl8169_private, wk.work);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006502 struct net_device *dev = tp->dev;
6503 int i;
Francois Romieu4422bcd2012-01-26 11:23:32 +01006504
Francois Romieuda78dbf2012-01-26 14:18:23 +01006505 rtl_lock_work(tp);
6506
Francois Romieu6c4a70c2012-01-31 10:56:44 +01006507 if (!netif_running(dev) ||
6508 !test_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags))
Francois Romieuda78dbf2012-01-26 14:18:23 +01006509 goto out_unlock;
6510
6511 for (i = 0; i < ARRAY_SIZE(rtl_work); i++) {
6512 bool pending;
6513
Francois Romieuda78dbf2012-01-26 14:18:23 +01006514 pending = test_and_clear_bit(rtl_work[i].bitnr, tp->wk.flags);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006515 if (pending)
6516 rtl_work[i].action(tp);
6517 }
6518
6519out_unlock:
6520 rtl_unlock_work(tp);
Francois Romieu4422bcd2012-01-26 11:23:32 +01006521}
6522
Stephen Hemmingerbea33482007-10-03 16:41:36 -07006523static int rtl8169_poll(struct napi_struct *napi, int budget)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006524{
Stephen Hemmingerbea33482007-10-03 16:41:36 -07006525 struct rtl8169_private *tp = container_of(napi, struct rtl8169_private, napi);
6526 struct net_device *dev = tp->dev;
Francois Romieuda78dbf2012-01-26 14:18:23 +01006527 u16 enable_mask = RTL_EVENT_NAPI | tp->event_slow;
6528 int work_done= 0;
6529 u16 status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006530
Francois Romieuda78dbf2012-01-26 14:18:23 +01006531 status = rtl_get_events(tp);
6532 rtl_ack_events(tp, status & ~tp->event_slow);
6533
6534 if (status & RTL_EVENT_NAPI_RX)
6535 work_done = rtl_rx(dev, tp, (u32) budget);
6536
6537 if (status & RTL_EVENT_NAPI_TX)
6538 rtl_tx(dev, tp);
6539
6540 if (status & tp->event_slow) {
6541 enable_mask &= ~tp->event_slow;
6542
6543 rtl_schedule_task(tp, RTL_FLAG_TASK_SLOW_PENDING);
6544 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006545
Stephen Hemmingerbea33482007-10-03 16:41:36 -07006546 if (work_done < budget) {
Ben Hutchings288379f2009-01-19 16:43:59 -08006547 napi_complete(napi);
David Dillowf11a3772009-05-22 15:29:34 +00006548
Francois Romieuda78dbf2012-01-26 14:18:23 +01006549 rtl_irq_enable(tp, enable_mask);
6550 mmiowb();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006551 }
6552
Stephen Hemmingerbea33482007-10-03 16:41:36 -07006553 return work_done;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006554}
Linus Torvalds1da177e2005-04-16 15:20:36 -07006555
Francois Romieu523a6092008-09-10 22:28:56 +02006556static void rtl8169_rx_missed(struct net_device *dev, void __iomem *ioaddr)
6557{
6558 struct rtl8169_private *tp = netdev_priv(dev);
6559
6560 if (tp->mac_version > RTL_GIGA_MAC_VER_06)
6561 return;
6562
6563 dev->stats.rx_missed_errors += (RTL_R32(RxMissed) & 0xffffff);
6564 RTL_W32(RxMissed, 0);
6565}
6566
Linus Torvalds1da177e2005-04-16 15:20:36 -07006567static void rtl8169_down(struct net_device *dev)
6568{
6569 struct rtl8169_private *tp = netdev_priv(dev);
6570 void __iomem *ioaddr = tp->mmio_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006571
Francois Romieu4876cc12011-03-11 21:07:11 +01006572 del_timer_sync(&tp->timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006573
Stephen Hemminger93dd79e2007-10-28 17:14:06 +01006574 napi_disable(&tp->napi);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006575 netif_stop_queue(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006576
Hayes Wang92fc43b2011-07-06 15:58:03 +08006577 rtl8169_hw_reset(tp);
Stanislaw Gruszka323bb682010-10-20 22:25:41 +00006578 /*
6579 * At this point device interrupts can not be enabled in any function,
Francois Romieu209e5ac2012-01-26 09:59:50 +01006580 * as netif_running is not true (rtl8169_interrupt, rtl8169_reset_task)
6581 * and napi is disabled (rtl8169_poll).
Stanislaw Gruszka323bb682010-10-20 22:25:41 +00006582 */
Francois Romieu523a6092008-09-10 22:28:56 +02006583 rtl8169_rx_missed(dev, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006584
Linus Torvalds1da177e2005-04-16 15:20:36 -07006585 /* Give a racing hard_start_xmit a few cycles to complete. */
Francois Romieuda78dbf2012-01-26 14:18:23 +01006586 synchronize_sched();
Linus Torvalds1da177e2005-04-16 15:20:36 -07006587
Linus Torvalds1da177e2005-04-16 15:20:36 -07006588 rtl8169_tx_clear(tp);
6589
6590 rtl8169_rx_clear(tp);
françois romieu065c27c2011-01-03 15:08:12 +00006591
6592 rtl_pll_power_down(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006593}
6594
6595static int rtl8169_close(struct net_device *dev)
6596{
6597 struct rtl8169_private *tp = netdev_priv(dev);
6598 struct pci_dev *pdev = tp->pci_dev;
6599
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006600 pm_runtime_get_sync(&pdev->dev);
6601
Francois Romieucecb5fd2011-04-01 10:21:07 +02006602 /* Update counters before going down */
Ivan Vecera355423d2009-02-06 21:49:57 -08006603 rtl8169_update_counters(dev);
6604
Francois Romieuda78dbf2012-01-26 14:18:23 +01006605 rtl_lock_work(tp);
Francois Romieu6c4a70c2012-01-31 10:56:44 +01006606 clear_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006607
Linus Torvalds1da177e2005-04-16 15:20:36 -07006608 rtl8169_down(dev);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006609 rtl_unlock_work(tp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006610
Lekensteyn4ea72442013-07-22 09:53:30 +02006611 cancel_work_sync(&tp->wk.work);
6612
Francois Romieu92a7c4e2012-03-10 10:42:12 +01006613 free_irq(pdev->irq, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006614
Stanislaw Gruszka82553bb2010-10-08 04:25:01 +00006615 dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray,
6616 tp->RxPhyAddr);
6617 dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray,
6618 tp->TxPhyAddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006619 tp->TxDescArray = NULL;
6620 tp->RxDescArray = NULL;
6621
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006622 pm_runtime_put_sync(&pdev->dev);
6623
Linus Torvalds1da177e2005-04-16 15:20:36 -07006624 return 0;
6625}
6626
Francois Romieudc1c00c2012-03-08 10:06:18 +01006627#ifdef CONFIG_NET_POLL_CONTROLLER
6628static void rtl8169_netpoll(struct net_device *dev)
6629{
6630 struct rtl8169_private *tp = netdev_priv(dev);
6631
6632 rtl8169_interrupt(tp->pci_dev->irq, dev);
6633}
6634#endif
6635
Francois Romieudf43ac72012-03-08 09:48:40 +01006636static int rtl_open(struct net_device *dev)
6637{
6638 struct rtl8169_private *tp = netdev_priv(dev);
6639 void __iomem *ioaddr = tp->mmio_addr;
6640 struct pci_dev *pdev = tp->pci_dev;
6641 int retval = -ENOMEM;
6642
6643 pm_runtime_get_sync(&pdev->dev);
6644
6645 /*
Jiri Kosinae75d6602012-04-08 21:48:52 +02006646 * Rx and Tx descriptors needs 256 bytes alignment.
Francois Romieudf43ac72012-03-08 09:48:40 +01006647 * dma_alloc_coherent provides more.
6648 */
6649 tp->TxDescArray = dma_alloc_coherent(&pdev->dev, R8169_TX_RING_BYTES,
6650 &tp->TxPhyAddr, GFP_KERNEL);
6651 if (!tp->TxDescArray)
6652 goto err_pm_runtime_put;
6653
6654 tp->RxDescArray = dma_alloc_coherent(&pdev->dev, R8169_RX_RING_BYTES,
6655 &tp->RxPhyAddr, GFP_KERNEL);
6656 if (!tp->RxDescArray)
6657 goto err_free_tx_0;
6658
6659 retval = rtl8169_init_ring(dev);
6660 if (retval < 0)
6661 goto err_free_rx_1;
6662
6663 INIT_WORK(&tp->wk.work, rtl_task);
6664
6665 smp_mb();
6666
6667 rtl_request_firmware(tp);
6668
Francois Romieu92a7c4e2012-03-10 10:42:12 +01006669 retval = request_irq(pdev->irq, rtl8169_interrupt,
Francois Romieudf43ac72012-03-08 09:48:40 +01006670 (tp->features & RTL_FEATURE_MSI) ? 0 : IRQF_SHARED,
6671 dev->name, dev);
6672 if (retval < 0)
6673 goto err_release_fw_2;
6674
6675 rtl_lock_work(tp);
6676
6677 set_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
6678
6679 napi_enable(&tp->napi);
6680
6681 rtl8169_init_phy(dev, tp);
6682
6683 __rtl8169_set_features(dev, dev->features);
6684
6685 rtl_pll_power_up(tp);
6686
6687 rtl_hw_start(dev);
6688
6689 netif_start_queue(dev);
6690
6691 rtl_unlock_work(tp);
6692
6693 tp->saved_wolopts = 0;
6694 pm_runtime_put_noidle(&pdev->dev);
6695
6696 rtl8169_check_link_status(dev, tp, ioaddr);
6697out:
6698 return retval;
6699
6700err_release_fw_2:
6701 rtl_release_firmware(tp);
6702 rtl8169_rx_clear(tp);
6703err_free_rx_1:
6704 dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray,
6705 tp->RxPhyAddr);
6706 tp->RxDescArray = NULL;
6707err_free_tx_0:
6708 dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray,
6709 tp->TxPhyAddr);
6710 tp->TxDescArray = NULL;
6711err_pm_runtime_put:
6712 pm_runtime_put_noidle(&pdev->dev);
6713 goto out;
6714}
6715
Junchang Wang8027aa22012-03-04 23:30:32 +01006716static struct rtnl_link_stats64 *
6717rtl8169_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006718{
6719 struct rtl8169_private *tp = netdev_priv(dev);
6720 void __iomem *ioaddr = tp->mmio_addr;
Junchang Wang8027aa22012-03-04 23:30:32 +01006721 unsigned int start;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006722
Francois Romieuda78dbf2012-01-26 14:18:23 +01006723 if (netif_running(dev))
Francois Romieu523a6092008-09-10 22:28:56 +02006724 rtl8169_rx_missed(dev, ioaddr);
Francois Romieu5b0384f2006-08-16 16:00:01 +02006725
Junchang Wang8027aa22012-03-04 23:30:32 +01006726 do {
Eric W. Biederman57a77442014-03-13 21:26:42 -07006727 start = u64_stats_fetch_begin_irq(&tp->rx_stats.syncp);
Junchang Wang8027aa22012-03-04 23:30:32 +01006728 stats->rx_packets = tp->rx_stats.packets;
6729 stats->rx_bytes = tp->rx_stats.bytes;
Eric W. Biederman57a77442014-03-13 21:26:42 -07006730 } while (u64_stats_fetch_retry_irq(&tp->rx_stats.syncp, start));
Junchang Wang8027aa22012-03-04 23:30:32 +01006731
6732
6733 do {
Eric W. Biederman57a77442014-03-13 21:26:42 -07006734 start = u64_stats_fetch_begin_irq(&tp->tx_stats.syncp);
Junchang Wang8027aa22012-03-04 23:30:32 +01006735 stats->tx_packets = tp->tx_stats.packets;
6736 stats->tx_bytes = tp->tx_stats.bytes;
Eric W. Biederman57a77442014-03-13 21:26:42 -07006737 } while (u64_stats_fetch_retry_irq(&tp->tx_stats.syncp, start));
Junchang Wang8027aa22012-03-04 23:30:32 +01006738
6739 stats->rx_dropped = dev->stats.rx_dropped;
6740 stats->tx_dropped = dev->stats.tx_dropped;
6741 stats->rx_length_errors = dev->stats.rx_length_errors;
6742 stats->rx_errors = dev->stats.rx_errors;
6743 stats->rx_crc_errors = dev->stats.rx_crc_errors;
6744 stats->rx_fifo_errors = dev->stats.rx_fifo_errors;
6745 stats->rx_missed_errors = dev->stats.rx_missed_errors;
6746
6747 return stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006748}
6749
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006750static void rtl8169_net_suspend(struct net_device *dev)
Francois Romieu5d06a992006-02-23 00:47:58 +01006751{
françois romieu065c27c2011-01-03 15:08:12 +00006752 struct rtl8169_private *tp = netdev_priv(dev);
6753
Francois Romieu5d06a992006-02-23 00:47:58 +01006754 if (!netif_running(dev))
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006755 return;
Francois Romieu5d06a992006-02-23 00:47:58 +01006756
6757 netif_device_detach(dev);
6758 netif_stop_queue(dev);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006759
6760 rtl_lock_work(tp);
6761 napi_disable(&tp->napi);
Francois Romieu6c4a70c2012-01-31 10:56:44 +01006762 clear_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006763 rtl_unlock_work(tp);
6764
6765 rtl_pll_power_down(tp);
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006766}
Francois Romieu5d06a992006-02-23 00:47:58 +01006767
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006768#ifdef CONFIG_PM
6769
6770static int rtl8169_suspend(struct device *device)
6771{
6772 struct pci_dev *pdev = to_pci_dev(device);
6773 struct net_device *dev = pci_get_drvdata(pdev);
6774
6775 rtl8169_net_suspend(dev);
Francois Romieu1371fa62007-04-02 23:01:11 +02006776
Francois Romieu5d06a992006-02-23 00:47:58 +01006777 return 0;
6778}
6779
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006780static void __rtl8169_resume(struct net_device *dev)
6781{
françois romieu065c27c2011-01-03 15:08:12 +00006782 struct rtl8169_private *tp = netdev_priv(dev);
6783
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006784 netif_device_attach(dev);
françois romieu065c27c2011-01-03 15:08:12 +00006785
6786 rtl_pll_power_up(tp);
6787
Artem Savkovcff4c162012-04-03 10:29:11 +00006788 rtl_lock_work(tp);
6789 napi_enable(&tp->napi);
Francois Romieu6c4a70c2012-01-31 10:56:44 +01006790 set_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
Artem Savkovcff4c162012-04-03 10:29:11 +00006791 rtl_unlock_work(tp);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006792
Francois Romieu98ddf982012-01-31 10:47:34 +01006793 rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006794}
6795
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006796static int rtl8169_resume(struct device *device)
Francois Romieu5d06a992006-02-23 00:47:58 +01006797{
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006798 struct pci_dev *pdev = to_pci_dev(device);
Francois Romieu5d06a992006-02-23 00:47:58 +01006799 struct net_device *dev = pci_get_drvdata(pdev);
Stanislaw Gruszkafccec102010-10-20 22:25:42 +00006800 struct rtl8169_private *tp = netdev_priv(dev);
6801
6802 rtl8169_init_phy(dev, tp);
Francois Romieu5d06a992006-02-23 00:47:58 +01006803
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006804 if (netif_running(dev))
6805 __rtl8169_resume(dev);
Francois Romieu5d06a992006-02-23 00:47:58 +01006806
Francois Romieu5d06a992006-02-23 00:47:58 +01006807 return 0;
6808}
6809
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006810static int rtl8169_runtime_suspend(struct device *device)
6811{
6812 struct pci_dev *pdev = to_pci_dev(device);
6813 struct net_device *dev = pci_get_drvdata(pdev);
6814 struct rtl8169_private *tp = netdev_priv(dev);
6815
6816 if (!tp->TxDescArray)
6817 return 0;
6818
Francois Romieuda78dbf2012-01-26 14:18:23 +01006819 rtl_lock_work(tp);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006820 tp->saved_wolopts = __rtl8169_get_wol(tp);
6821 __rtl8169_set_wol(tp, WAKE_ANY);
Francois Romieuda78dbf2012-01-26 14:18:23 +01006822 rtl_unlock_work(tp);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006823
6824 rtl8169_net_suspend(dev);
6825
6826 return 0;
6827}
6828
6829static int rtl8169_runtime_resume(struct device *device)
6830{
6831 struct pci_dev *pdev = to_pci_dev(device);
6832 struct net_device *dev = pci_get_drvdata(pdev);
6833 struct rtl8169_private *tp = netdev_priv(dev);
6834
6835 if (!tp->TxDescArray)
6836 return 0;
6837
Francois Romieuda78dbf2012-01-26 14:18:23 +01006838 rtl_lock_work(tp);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006839 __rtl8169_set_wol(tp, tp->saved_wolopts);
6840 tp->saved_wolopts = 0;
Francois Romieuda78dbf2012-01-26 14:18:23 +01006841 rtl_unlock_work(tp);
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006842
Stanislaw Gruszkafccec102010-10-20 22:25:42 +00006843 rtl8169_init_phy(dev, tp);
6844
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006845 __rtl8169_resume(dev);
6846
6847 return 0;
6848}
6849
6850static int rtl8169_runtime_idle(struct device *device)
6851{
6852 struct pci_dev *pdev = to_pci_dev(device);
6853 struct net_device *dev = pci_get_drvdata(pdev);
6854 struct rtl8169_private *tp = netdev_priv(dev);
6855
Rafael J. Wysockie4fbce72010-12-08 15:32:14 +00006856 return tp->TxDescArray ? -EBUSY : 0;
Rafael J. Wysockie1759442010-03-14 14:33:51 +00006857}
6858
Alexey Dobriyan47145212009-12-14 18:00:08 -08006859static const struct dev_pm_ops rtl8169_pm_ops = {
Francois Romieucecb5fd2011-04-01 10:21:07 +02006860 .suspend = rtl8169_suspend,
6861 .resume = rtl8169_resume,
6862 .freeze = rtl8169_suspend,
6863 .thaw = rtl8169_resume,
6864 .poweroff = rtl8169_suspend,
6865 .restore = rtl8169_resume,
6866 .runtime_suspend = rtl8169_runtime_suspend,
6867 .runtime_resume = rtl8169_runtime_resume,
6868 .runtime_idle = rtl8169_runtime_idle,
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006869};
6870
6871#define RTL8169_PM_OPS (&rtl8169_pm_ops)
6872
6873#else /* !CONFIG_PM */
6874
6875#define RTL8169_PM_OPS NULL
6876
6877#endif /* !CONFIG_PM */
6878
David S. Miller1805b2f2011-10-24 18:18:09 -04006879static void rtl_wol_shutdown_quirk(struct rtl8169_private *tp)
6880{
6881 void __iomem *ioaddr = tp->mmio_addr;
6882
6883 /* WoL fails with 8168b when the receiver is disabled. */
6884 switch (tp->mac_version) {
6885 case RTL_GIGA_MAC_VER_11:
6886 case RTL_GIGA_MAC_VER_12:
6887 case RTL_GIGA_MAC_VER_17:
6888 pci_clear_master(tp->pci_dev);
6889
6890 RTL_W8(ChipCmd, CmdRxEnb);
6891 /* PCI commit */
6892 RTL_R8(ChipCmd);
6893 break;
6894 default:
6895 break;
6896 }
6897}
6898
Francois Romieu1765f952008-09-13 17:21:40 +02006899static void rtl_shutdown(struct pci_dev *pdev)
6900{
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006901 struct net_device *dev = pci_get_drvdata(pdev);
françois romieu4bb3f522009-06-17 11:41:45 +00006902 struct rtl8169_private *tp = netdev_priv(dev);
françois romieu2a15cd22012-03-06 01:14:12 +00006903 struct device *d = &pdev->dev;
6904
6905 pm_runtime_get_sync(d);
Francois Romieu1765f952008-09-13 17:21:40 +02006906
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006907 rtl8169_net_suspend(dev);
6908
Francois Romieucecb5fd2011-04-01 10:21:07 +02006909 /* Restore original MAC address */
Ivan Veceracc098dc2009-11-29 23:12:52 -08006910 rtl_rar_set(tp, dev->perm_addr);
6911
Hayes Wang92fc43b2011-07-06 15:58:03 +08006912 rtl8169_hw_reset(tp);
françois romieu4bb3f522009-06-17 11:41:45 +00006913
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006914 if (system_state == SYSTEM_POWER_OFF) {
David S. Miller1805b2f2011-10-24 18:18:09 -04006915 if (__rtl8169_get_wol(tp) & WAKE_ANY) {
6916 rtl_wol_suspend_quirk(tp);
6917 rtl_wol_shutdown_quirk(tp);
françois romieuca52efd2009-07-24 12:34:19 +00006918 }
6919
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006920 pci_wake_from_d3(pdev, true);
6921 pci_set_power_state(pdev, PCI_D3hot);
6922 }
françois romieu2a15cd22012-03-06 01:14:12 +00006923
6924 pm_runtime_put_noidle(d);
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00006925}
Francois Romieu5d06a992006-02-23 00:47:58 +01006926
Bill Pembertonbaf63292012-12-03 09:23:28 -05006927static void rtl_remove_one(struct pci_dev *pdev)
Francois Romieue27566e2012-03-08 09:54:01 +01006928{
6929 struct net_device *dev = pci_get_drvdata(pdev);
6930 struct rtl8169_private *tp = netdev_priv(dev);
6931
6932 if (tp->mac_version == RTL_GIGA_MAC_VER_27 ||
6933 tp->mac_version == RTL_GIGA_MAC_VER_28 ||
6934 tp->mac_version == RTL_GIGA_MAC_VER_31) {
6935 rtl8168_driver_stop(tp);
6936 }
6937
Devendra Nagaad1be8d2012-05-31 01:51:20 +00006938 netif_napi_del(&tp->napi);
6939
Francois Romieue27566e2012-03-08 09:54:01 +01006940 unregister_netdev(dev);
6941
6942 rtl_release_firmware(tp);
6943
6944 if (pci_dev_run_wake(pdev))
6945 pm_runtime_get_noresume(&pdev->dev);
6946
6947 /* restore original MAC address */
6948 rtl_rar_set(tp, dev->perm_addr);
6949
6950 rtl_disable_msi(pdev, tp);
6951 rtl8169_release_board(pdev, dev, tp->mmio_addr);
Francois Romieue27566e2012-03-08 09:54:01 +01006952}
6953
Francois Romieufa9c3852012-03-08 10:01:50 +01006954static const struct net_device_ops rtl_netdev_ops = {
Francois Romieudf43ac72012-03-08 09:48:40 +01006955 .ndo_open = rtl_open,
Francois Romieufa9c3852012-03-08 10:01:50 +01006956 .ndo_stop = rtl8169_close,
6957 .ndo_get_stats64 = rtl8169_get_stats64,
6958 .ndo_start_xmit = rtl8169_start_xmit,
6959 .ndo_tx_timeout = rtl8169_tx_timeout,
6960 .ndo_validate_addr = eth_validate_addr,
6961 .ndo_change_mtu = rtl8169_change_mtu,
6962 .ndo_fix_features = rtl8169_fix_features,
6963 .ndo_set_features = rtl8169_set_features,
6964 .ndo_set_mac_address = rtl_set_mac_address,
6965 .ndo_do_ioctl = rtl8169_ioctl,
6966 .ndo_set_rx_mode = rtl_set_rx_mode,
6967#ifdef CONFIG_NET_POLL_CONTROLLER
6968 .ndo_poll_controller = rtl8169_netpoll,
6969#endif
6970
6971};
6972
Francois Romieu31fa8b12012-03-08 10:09:40 +01006973static const struct rtl_cfg_info {
6974 void (*hw_start)(struct net_device *);
6975 unsigned int region;
6976 unsigned int align;
6977 u16 event_slow;
6978 unsigned features;
6979 u8 default_ver;
6980} rtl_cfg_infos [] = {
6981 [RTL_CFG_0] = {
6982 .hw_start = rtl_hw_start_8169,
6983 .region = 1,
6984 .align = 0,
6985 .event_slow = SYSErr | LinkChg | RxOverflow | RxFIFOOver,
6986 .features = RTL_FEATURE_GMII,
6987 .default_ver = RTL_GIGA_MAC_VER_01,
6988 },
6989 [RTL_CFG_1] = {
6990 .hw_start = rtl_hw_start_8168,
6991 .region = 2,
6992 .align = 8,
6993 .event_slow = SYSErr | LinkChg | RxOverflow,
6994 .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI,
6995 .default_ver = RTL_GIGA_MAC_VER_11,
6996 },
6997 [RTL_CFG_2] = {
6998 .hw_start = rtl_hw_start_8101,
6999 .region = 2,
7000 .align = 8,
7001 .event_slow = SYSErr | LinkChg | RxOverflow | RxFIFOOver |
7002 PCSTimeout,
7003 .features = RTL_FEATURE_MSI,
7004 .default_ver = RTL_GIGA_MAC_VER_13,
7005 }
7006};
7007
7008/* Cfg9346_Unlock assumed. */
7009static unsigned rtl_try_msi(struct rtl8169_private *tp,
7010 const struct rtl_cfg_info *cfg)
7011{
7012 void __iomem *ioaddr = tp->mmio_addr;
7013 unsigned msi = 0;
7014 u8 cfg2;
7015
7016 cfg2 = RTL_R8(Config2) & ~MSIEnable;
7017 if (cfg->features & RTL_FEATURE_MSI) {
7018 if (pci_enable_msi(tp->pci_dev)) {
7019 netif_info(tp, hw, tp->dev, "no MSI. Back to INTx.\n");
7020 } else {
7021 cfg2 |= MSIEnable;
7022 msi = RTL_FEATURE_MSI;
7023 }
7024 }
7025 if (tp->mac_version <= RTL_GIGA_MAC_VER_06)
7026 RTL_W8(Config2, cfg2);
7027 return msi;
7028}
7029
Hayes Wangc5583862012-07-02 17:23:22 +08007030DECLARE_RTL_COND(rtl_link_list_ready_cond)
7031{
7032 void __iomem *ioaddr = tp->mmio_addr;
7033
7034 return RTL_R8(MCU) & LINK_LIST_RDY;
7035}
7036
7037DECLARE_RTL_COND(rtl_rxtx_empty_cond)
7038{
7039 void __iomem *ioaddr = tp->mmio_addr;
7040
7041 return (RTL_R8(MCU) & RXTX_EMPTY) == RXTX_EMPTY;
7042}
7043
Bill Pembertonbaf63292012-12-03 09:23:28 -05007044static void rtl_hw_init_8168g(struct rtl8169_private *tp)
Hayes Wangc5583862012-07-02 17:23:22 +08007045{
7046 void __iomem *ioaddr = tp->mmio_addr;
7047 u32 data;
7048
7049 tp->ocp_base = OCP_STD_PHY_BASE;
7050
7051 RTL_W32(MISC, RTL_R32(MISC) | RXDV_GATED_EN);
7052
7053 if (!rtl_udelay_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 42))
7054 return;
7055
7056 if (!rtl_udelay_loop_wait_high(tp, &rtl_rxtx_empty_cond, 100, 42))
7057 return;
7058
7059 RTL_W8(ChipCmd, RTL_R8(ChipCmd) & ~(CmdTxEnb | CmdRxEnb));
7060 msleep(1);
7061 RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
7062
Hayes Wang5f8bcce2012-07-10 08:47:05 +02007063 data = r8168_mac_ocp_read(tp, 0xe8de);
Hayes Wangc5583862012-07-02 17:23:22 +08007064 data &= ~(1 << 14);
7065 r8168_mac_ocp_write(tp, 0xe8de, data);
7066
7067 if (!rtl_udelay_loop_wait_high(tp, &rtl_link_list_ready_cond, 100, 42))
7068 return;
7069
Hayes Wang5f8bcce2012-07-10 08:47:05 +02007070 data = r8168_mac_ocp_read(tp, 0xe8de);
Hayes Wangc5583862012-07-02 17:23:22 +08007071 data |= (1 << 15);
7072 r8168_mac_ocp_write(tp, 0xe8de, data);
7073
7074 if (!rtl_udelay_loop_wait_high(tp, &rtl_link_list_ready_cond, 100, 42))
7075 return;
7076}
7077
Bill Pembertonbaf63292012-12-03 09:23:28 -05007078static void rtl_hw_initialize(struct rtl8169_private *tp)
Hayes Wangc5583862012-07-02 17:23:22 +08007079{
7080 switch (tp->mac_version) {
7081 case RTL_GIGA_MAC_VER_40:
7082 case RTL_GIGA_MAC_VER_41:
hayeswang57538c42013-04-01 22:23:40 +00007083 case RTL_GIGA_MAC_VER_42:
hayeswang58152cd2013-04-01 22:23:42 +00007084 case RTL_GIGA_MAC_VER_43:
hayeswang45dd95c2013-07-08 17:09:01 +08007085 case RTL_GIGA_MAC_VER_44:
Hayes Wangc5583862012-07-02 17:23:22 +08007086 rtl_hw_init_8168g(tp);
7087 break;
7088
7089 default:
7090 break;
7091 }
7092}
7093
Bill Pembertonbaf63292012-12-03 09:23:28 -05007094static int
Francois Romieu3b6cf252012-03-08 09:59:04 +01007095rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
7096{
7097 const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data;
7098 const unsigned int region = cfg->region;
7099 struct rtl8169_private *tp;
7100 struct mii_if_info *mii;
7101 struct net_device *dev;
7102 void __iomem *ioaddr;
7103 int chipset, i;
7104 int rc;
7105
7106 if (netif_msg_drv(&debug)) {
7107 printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n",
7108 MODULENAME, RTL8169_VERSION);
7109 }
7110
7111 dev = alloc_etherdev(sizeof (*tp));
7112 if (!dev) {
7113 rc = -ENOMEM;
7114 goto out;
7115 }
7116
7117 SET_NETDEV_DEV(dev, &pdev->dev);
Francois Romieufa9c3852012-03-08 10:01:50 +01007118 dev->netdev_ops = &rtl_netdev_ops;
Francois Romieu3b6cf252012-03-08 09:59:04 +01007119 tp = netdev_priv(dev);
7120 tp->dev = dev;
7121 tp->pci_dev = pdev;
7122 tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT);
7123
7124 mii = &tp->mii;
7125 mii->dev = dev;
7126 mii->mdio_read = rtl_mdio_read;
7127 mii->mdio_write = rtl_mdio_write;
7128 mii->phy_id_mask = 0x1f;
7129 mii->reg_num_mask = 0x1f;
7130 mii->supports_gmii = !!(cfg->features & RTL_FEATURE_GMII);
7131
7132 /* disable ASPM completely as that cause random device stop working
7133 * problems as well as full system hangs for some PCIe devices users */
7134 pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
7135 PCIE_LINK_STATE_CLKPM);
7136
7137 /* enable device (incl. PCI PM wakeup and hotplug setup) */
7138 rc = pci_enable_device(pdev);
7139 if (rc < 0) {
7140 netif_err(tp, probe, dev, "enable failure\n");
7141 goto err_out_free_dev_1;
7142 }
7143
7144 if (pci_set_mwi(pdev) < 0)
7145 netif_info(tp, probe, dev, "Mem-Wr-Inval unavailable\n");
7146
7147 /* make sure PCI base addr 1 is MMIO */
7148 if (!(pci_resource_flags(pdev, region) & IORESOURCE_MEM)) {
7149 netif_err(tp, probe, dev,
7150 "region #%d not an MMIO resource, aborting\n",
7151 region);
7152 rc = -ENODEV;
7153 goto err_out_mwi_2;
7154 }
7155
7156 /* check for weird/broken PCI region reporting */
7157 if (pci_resource_len(pdev, region) < R8169_REGS_SIZE) {
7158 netif_err(tp, probe, dev,
7159 "Invalid PCI region size(s), aborting\n");
7160 rc = -ENODEV;
7161 goto err_out_mwi_2;
7162 }
7163
7164 rc = pci_request_regions(pdev, MODULENAME);
7165 if (rc < 0) {
7166 netif_err(tp, probe, dev, "could not request regions\n");
7167 goto err_out_mwi_2;
7168 }
7169
7170 tp->cp_cmd = RxChkSum;
7171
7172 if ((sizeof(dma_addr_t) > 4) &&
7173 !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && use_dac) {
7174 tp->cp_cmd |= PCIDAC;
7175 dev->features |= NETIF_F_HIGHDMA;
7176 } else {
7177 rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
7178 if (rc < 0) {
7179 netif_err(tp, probe, dev, "DMA configuration failed\n");
7180 goto err_out_free_res_3;
7181 }
7182 }
7183
7184 /* ioremap MMIO region */
7185 ioaddr = ioremap(pci_resource_start(pdev, region), R8169_REGS_SIZE);
7186 if (!ioaddr) {
7187 netif_err(tp, probe, dev, "cannot remap MMIO, aborting\n");
7188 rc = -EIO;
7189 goto err_out_free_res_3;
7190 }
7191 tp->mmio_addr = ioaddr;
7192
7193 if (!pci_is_pcie(pdev))
7194 netif_info(tp, probe, dev, "not PCI Express\n");
7195
7196 /* Identify chip attached to board */
7197 rtl8169_get_mac_version(tp, dev, cfg->default_ver);
7198
7199 rtl_init_rxcfg(tp);
7200
7201 rtl_irq_disable(tp);
7202
Hayes Wangc5583862012-07-02 17:23:22 +08007203 rtl_hw_initialize(tp);
7204
Francois Romieu3b6cf252012-03-08 09:59:04 +01007205 rtl_hw_reset(tp);
7206
7207 rtl_ack_events(tp, 0xffff);
7208
7209 pci_set_master(pdev);
7210
7211 /*
7212 * Pretend we are using VLANs; This bypasses a nasty bug where
7213 * Interrupts stop flowing on high load on 8110SCd controllers.
7214 */
7215 if (tp->mac_version == RTL_GIGA_MAC_VER_05)
7216 tp->cp_cmd |= RxVlan;
7217
7218 rtl_init_mdio_ops(tp);
7219 rtl_init_pll_power_ops(tp);
7220 rtl_init_jumbo_ops(tp);
Hayes Wangbeb1fe12012-03-30 14:33:01 +08007221 rtl_init_csi_ops(tp);
Francois Romieu3b6cf252012-03-08 09:59:04 +01007222
7223 rtl8169_print_mac_version(tp);
7224
7225 chipset = tp->mac_version;
7226 tp->txd_version = rtl_chip_infos[chipset].txd_version;
7227
7228 RTL_W8(Cfg9346, Cfg9346_Unlock);
7229 RTL_W8(Config1, RTL_R8(Config1) | PMEnable);
Peter Wu8f9d5132013-08-17 11:00:02 +02007230 RTL_W8(Config5, RTL_R8(Config5) & (BWF | MWF | UWF | LanWake | PMEStatus));
Francois Romieu3b6cf252012-03-08 09:59:04 +01007231 if ((RTL_R8(Config3) & (LinkUp | MagicPacket)) != 0)
7232 tp->features |= RTL_FEATURE_WOL;
7233 if ((RTL_R8(Config5) & (UWF | BWF | MWF)) != 0)
7234 tp->features |= RTL_FEATURE_WOL;
7235 tp->features |= rtl_try_msi(tp, cfg);
7236 RTL_W8(Cfg9346, Cfg9346_Lock);
7237
7238 if (rtl_tbi_enabled(tp)) {
7239 tp->set_speed = rtl8169_set_speed_tbi;
7240 tp->get_settings = rtl8169_gset_tbi;
7241 tp->phy_reset_enable = rtl8169_tbi_reset_enable;
7242 tp->phy_reset_pending = rtl8169_tbi_reset_pending;
7243 tp->link_ok = rtl8169_tbi_link_ok;
7244 tp->do_ioctl = rtl_tbi_ioctl;
7245 } else {
7246 tp->set_speed = rtl8169_set_speed_xmii;
7247 tp->get_settings = rtl8169_gset_xmii;
7248 tp->phy_reset_enable = rtl8169_xmii_reset_enable;
7249 tp->phy_reset_pending = rtl8169_xmii_reset_pending;
7250 tp->link_ok = rtl8169_xmii_link_ok;
7251 tp->do_ioctl = rtl_xmii_ioctl;
7252 }
7253
7254 mutex_init(&tp->wk.mutex);
Kyle McMartin340fea32014-02-24 20:12:28 -05007255 u64_stats_init(&tp->rx_stats.syncp);
7256 u64_stats_init(&tp->tx_stats.syncp);
Francois Romieu3b6cf252012-03-08 09:59:04 +01007257
7258 /* Get MAC address */
7259 for (i = 0; i < ETH_ALEN; i++)
7260 dev->dev_addr[i] = RTL_R8(MAC0 + i);
Francois Romieu3b6cf252012-03-08 09:59:04 +01007261
Wilfried Klaebe7ad24ea2014-05-11 00:12:32 +00007262 dev->ethtool_ops = &rtl8169_ethtool_ops;
Francois Romieu3b6cf252012-03-08 09:59:04 +01007263 dev->watchdog_timeo = RTL8169_TX_TIMEOUT;
Francois Romieu3b6cf252012-03-08 09:59:04 +01007264
7265 netif_napi_add(dev, &tp->napi, rtl8169_poll, R8169_NAPI_WEIGHT);
7266
7267 /* don't enable SG, IP_CSUM and TSO by default - it might not work
7268 * properly for all devices */
7269 dev->features |= NETIF_F_RXCSUM |
Patrick McHardyf6469682013-04-19 02:04:27 +00007270 NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX;
Francois Romieu3b6cf252012-03-08 09:59:04 +01007271
7272 dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
Patrick McHardyf6469682013-04-19 02:04:27 +00007273 NETIF_F_RXCSUM | NETIF_F_HW_VLAN_CTAG_TX |
7274 NETIF_F_HW_VLAN_CTAG_RX;
Francois Romieu3b6cf252012-03-08 09:59:04 +01007275 dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
7276 NETIF_F_HIGHDMA;
7277
7278 if (tp->mac_version == RTL_GIGA_MAC_VER_05)
7279 /* 8110SCd requires hardware Rx VLAN - disallow toggling */
Patrick McHardyf6469682013-04-19 02:04:27 +00007280 dev->hw_features &= ~NETIF_F_HW_VLAN_CTAG_RX;
Francois Romieu3b6cf252012-03-08 09:59:04 +01007281
hayeswang5888d3f2014-07-11 16:25:56 +08007282 if (tp->txd_version == RTL_TD_0)
7283 tp->tso_csum = rtl8169_tso_csum_v1;
hayeswange9746042014-07-11 16:25:58 +08007284 else if (tp->txd_version == RTL_TD_1) {
hayeswang5888d3f2014-07-11 16:25:56 +08007285 tp->tso_csum = rtl8169_tso_csum_v2;
hayeswange9746042014-07-11 16:25:58 +08007286 dev->hw_features |= NETIF_F_IPV6_CSUM | NETIF_F_TSO6;
7287 } else
hayeswang5888d3f2014-07-11 16:25:56 +08007288 WARN_ON_ONCE(1);
7289
Francois Romieu3b6cf252012-03-08 09:59:04 +01007290 dev->hw_features |= NETIF_F_RXALL;
7291 dev->hw_features |= NETIF_F_RXFCS;
7292
7293 tp->hw_start = cfg->hw_start;
7294 tp->event_slow = cfg->event_slow;
7295
7296 tp->opts1_mask = (tp->mac_version != RTL_GIGA_MAC_VER_01) ?
7297 ~(RxBOVF | RxFOVF) : ~0;
7298
7299 init_timer(&tp->timer);
7300 tp->timer.data = (unsigned long) dev;
7301 tp->timer.function = rtl8169_phy_timer;
7302
7303 tp->rtl_fw = RTL_FIRMWARE_UNKNOWN;
7304
7305 rc = register_netdev(dev);
7306 if (rc < 0)
7307 goto err_out_msi_4;
7308
7309 pci_set_drvdata(pdev, dev);
7310
Francois Romieu92a7c4e2012-03-10 10:42:12 +01007311 netif_info(tp, probe, dev, "%s at 0x%p, %pM, XID %08x IRQ %d\n",
7312 rtl_chip_infos[chipset].name, ioaddr, dev->dev_addr,
7313 (u32)(RTL_R32(TxConfig) & 0x9cf0f8ff), pdev->irq);
Francois Romieu3b6cf252012-03-08 09:59:04 +01007314 if (rtl_chip_infos[chipset].jumbo_max != JUMBO_1K) {
7315 netif_info(tp, probe, dev, "jumbo features [frames: %d bytes, "
7316 "tx checksumming: %s]\n",
7317 rtl_chip_infos[chipset].jumbo_max,
7318 rtl_chip_infos[chipset].jumbo_tx_csum ? "ok" : "ko");
7319 }
7320
7321 if (tp->mac_version == RTL_GIGA_MAC_VER_27 ||
7322 tp->mac_version == RTL_GIGA_MAC_VER_28 ||
7323 tp->mac_version == RTL_GIGA_MAC_VER_31) {
7324 rtl8168_driver_start(tp);
7325 }
7326
7327 device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL);
7328
7329 if (pci_dev_run_wake(pdev))
7330 pm_runtime_put_noidle(&pdev->dev);
7331
7332 netif_carrier_off(dev);
7333
7334out:
7335 return rc;
7336
7337err_out_msi_4:
Devendra Nagaad1be8d2012-05-31 01:51:20 +00007338 netif_napi_del(&tp->napi);
Francois Romieu3b6cf252012-03-08 09:59:04 +01007339 rtl_disable_msi(pdev, tp);
7340 iounmap(ioaddr);
7341err_out_free_res_3:
7342 pci_release_regions(pdev);
7343err_out_mwi_2:
7344 pci_clear_mwi(pdev);
7345 pci_disable_device(pdev);
7346err_out_free_dev_1:
7347 free_netdev(dev);
7348 goto out;
7349}
7350
Linus Torvalds1da177e2005-04-16 15:20:36 -07007351static struct pci_driver rtl8169_pci_driver = {
7352 .name = MODULENAME,
7353 .id_table = rtl8169_pci_tbl,
Francois Romieu3b6cf252012-03-08 09:59:04 +01007354 .probe = rtl_init_one,
Bill Pembertonbaf63292012-12-03 09:23:28 -05007355 .remove = rtl_remove_one,
Francois Romieu1765f952008-09-13 17:21:40 +02007356 .shutdown = rtl_shutdown,
Rafael J. Wysocki861ab442009-04-05 08:40:04 +00007357 .driver.pm = RTL8169_PM_OPS,
Linus Torvalds1da177e2005-04-16 15:20:36 -07007358};
7359
Devendra Naga3eeb7da2012-10-26 09:27:42 +00007360module_pci_driver(rtl8169_pci_driver);