diff mbox

[net-next-2.6,01/08] r8169: remove the firmware of RTL8111D.

Message ID 20110102233552.GB5780@electric-eye.fr.zoreil.com
State Changes Requested, archived
Delegated to: David Miller
Headers show

Commit Message

Francois Romieu Jan. 2, 2011, 11:35 p.m. UTC
The binary file of the firmware is moved to linux-firmware repository.
The firmwares are rtl_nic/rtl8168d-1.fw and rtl_nic/rtl8168d-2.fw.
The driver goes along if the firmware couldn't be found. However, it
is suggested to be done with the suitable firmware.

Some wrong PHY parameters are directly corrected in the driver.

Simple firmware checking added per Ben Hutchings suggestion.

Signed-off-by: Hayes Wang <hayeswang@realtek.com>
Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
Cc: Ben Hutchings <benh@debian.org>
---
 drivers/net/r8169.c |  812 +++++++++------------------------------------------
 1 files changed, 133 insertions(+), 679 deletions(-)

Comments

Ben Hutchings Jan. 3, 2011, 11:09 p.m. UTC | #1
On Mon, 2011-01-03 at 00:35 +0100, Francois Romieu wrote:
> The binary file of the firmware is moved to linux-firmware repository.
> The firmwares are rtl_nic/rtl8168d-1.fw and rtl_nic/rtl8168d-2.fw.
> The driver goes along if the firmware couldn't be found. However, it
> is suggested to be done with the suitable firmware.
[...]

You should also add 'select FW_LOADER' to the Kconfig section for R8169.

Ben.
diff mbox

Patch

diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index e165d96..3124462 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -24,6 +24,7 @@ 
 #include <linux/init.h>
 #include <linux/dma-mapping.h>
 #include <linux/pm_runtime.h>
+#include <linux/firmware.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -33,6 +34,9 @@ 
 #define MODULENAME "r8169"
 #define PFX MODULENAME ": "
 
+#define FIRMWARE_8168D_1	"rtl_nic/rtl8168d-1.fw"
+#define FIRMWARE_8168D_2	"rtl_nic/rtl8168d-2.fw"
+
 #ifdef RTL8169_DEBUG
 #define assert(expr) \
 	if (!(expr)) {					\
@@ -514,6 +518,8 @@  module_param_named(debug, debug.msg_enable, int, 0);
 MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(RTL8169_VERSION);
+MODULE_FIRMWARE(FIRMWARE_8168D_1);
+MODULE_FIRMWARE(FIRMWARE_8168D_2);
 
 static int rtl8169_open(struct net_device *dev);
 static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
@@ -1393,6 +1399,65 @@  static void rtl_phy_write(void __iomem *ioaddr, const struct phy_reg *regs, int
 	}
 }
 
+#define PHY_READ		0x00000000
+#define PHY_DATA_OR		0x10000000
+#define PHY_DATA_AND		0x20000000
+#define PHY_BJMPN		0x30000000
+#define PHY_READ_EFUSE		0x40000000
+#define PHY_READ_MAC_BYTE	0x50000000
+#define PHY_WRITE_MAC_BYTE	0x60000000
+#define PHY_CLEAR_READCOUNT	0x70000000
+#define PHY_WRITE		0x80000000
+#define PHY_READCOUNT_EQ_SKIP	0x90000000
+#define PHY_COMP_EQ_SKIPN	0xa0000000
+#define PHY_COMP_NEQ_SKIPN	0xb0000000
+#define PHY_WRITE_PREVIOUS	0xc0000000
+#define PHY_SKIPN		0xd0000000
+#define PHY_DELAY_MS		0xe0000000
+#define PHY_WRITE_ERI_WORD	0xf0000000
+
+static void
+rtl_phy_write_fw(struct rtl8169_private *tp, const struct firmware *fw)
+{
+	void __iomem *ioaddr = tp->mmio_addr;
+	__le32 *phytable = (__le32 *)fw->data;
+	struct net_device *dev = tp->dev;
+	size_t i;
+
+	if (fw->size % sizeof(*phytable)) {
+		netif_err(tp, probe, dev, "odd sized firmware %zd\n", fw->size);
+		return;
+	}
+
+	for (i = 0; i < fw->size / sizeof(*phytable); i++) {
+		u32 action = le32_to_cpu(phytable[i]);
+
+		if (!action)
+			break;
+
+		if ((action & 0xf0000000) != PHY_WRITE) {
+			netif_err(tp, probe, dev,
+				  "unknown action 0x%08x\n", action);
+			return;
+		}
+	}
+
+	while (i-- != 0) {
+		u32 action = le32_to_cpu(*phytable);
+		u32 data = action & 0x0000ffff;
+		u32 reg = (action & 0x0fff0000) >> 16;
+
+		switch(action & 0xf0000000) {
+		case PHY_WRITE:
+			mdio_write(ioaddr, reg, data);
+			phytable++;
+			break;
+		default:
+			BUG();
+		}
+	}
+}
+
 static void rtl8169s_hw_phy_config(void __iomem *ioaddr)
 {
 	static const struct phy_reg phy_reg_init[] = {
@@ -1725,9 +1790,10 @@  static void rtl8168c_4_hw_phy_config(void __iomem *ioaddr)
 	rtl8168c_3_hw_phy_config(ioaddr);
 }
 
-static void rtl8168d_1_hw_phy_config(void __iomem *ioaddr)
+static void rtl8168d_1_hw_phy_config(struct rtl8169_private *tp)
 {
 	static const struct phy_reg phy_reg_init_0[] = {
+		/* Channel Estimation */
 		{ 0x1f, 0x0001 },
 		{ 0x06, 0x4064 },
 		{ 0x07, 0x2863 },
@@ -1744,379 +1810,41 @@  static void rtl8168d_1_hw_phy_config(void __iomem *ioaddr)
 		{ 0x12, 0xf49f },
 		{ 0x13, 0x070b },
 		{ 0x1a, 0x05ad },
-		{ 0x14, 0x94c0 }
-	};
-	static const struct phy_reg phy_reg_init_1[] = {
+		{ 0x14, 0x94c0 },
+
+		/*
+		 * Tx Error Issue
+		 * enhance line driver power
+		 */
 		{ 0x1f, 0x0002 },
 		{ 0x06, 0x5561 },
 		{ 0x1f, 0x0005 },
 		{ 0x05, 0x8332 },
-		{ 0x06, 0x5561 }
-	};
-	static const struct phy_reg phy_reg_init_2[] = {
-		{ 0x1f, 0x0005 },
-		{ 0x05, 0xffc2 },
-		{ 0x1f, 0x0005 },
-		{ 0x05, 0x8000 },
-		{ 0x06, 0xf8f9 },
-		{ 0x06, 0xfaef },
-		{ 0x06, 0x59ee },
-		{ 0x06, 0xf8ea },
-		{ 0x06, 0x00ee },
-		{ 0x06, 0xf8eb },
-		{ 0x06, 0x00e0 },
-		{ 0x06, 0xf87c },
-		{ 0x06, 0xe1f8 },
-		{ 0x06, 0x7d59 },
-		{ 0x06, 0x0fef },
-		{ 0x06, 0x0139 },
-		{ 0x06, 0x029e },
-		{ 0x06, 0x06ef },
-		{ 0x06, 0x1039 },
-		{ 0x06, 0x089f },
-		{ 0x06, 0x2aee },
-		{ 0x06, 0xf8ea },
-		{ 0x06, 0x00ee },
-		{ 0x06, 0xf8eb },
-		{ 0x06, 0x01e0 },
-		{ 0x06, 0xf87c },
-		{ 0x06, 0xe1f8 },
-		{ 0x06, 0x7d58 },
-		{ 0x06, 0x409e },
-		{ 0x06, 0x0f39 },
-		{ 0x06, 0x46aa },
-		{ 0x06, 0x0bbf },
-		{ 0x06, 0x8290 },
-		{ 0x06, 0xd682 },
-		{ 0x06, 0x9802 },
-		{ 0x06, 0x014f },
-		{ 0x06, 0xae09 },
-		{ 0x06, 0xbf82 },
-		{ 0x06, 0x98d6 },
-		{ 0x06, 0x82a0 },
-		{ 0x06, 0x0201 },
-		{ 0x06, 0x4fef },
-		{ 0x06, 0x95fe },
-		{ 0x06, 0xfdfc },
-		{ 0x06, 0x05f8 },
-		{ 0x06, 0xf9fa },
-		{ 0x06, 0xeef8 },
-		{ 0x06, 0xea00 },
-		{ 0x06, 0xeef8 },
-		{ 0x06, 0xeb00 },
-		{ 0x06, 0xe2f8 },
-		{ 0x06, 0x7ce3 },
-		{ 0x06, 0xf87d },
-		{ 0x06, 0xa511 },
-		{ 0x06, 0x1112 },
-		{ 0x06, 0xd240 },
-		{ 0x06, 0xd644 },
-		{ 0x06, 0x4402 },
-		{ 0x06, 0x8217 },
-		{ 0x06, 0xd2a0 },
-		{ 0x06, 0xd6aa },
-		{ 0x06, 0xaa02 },
-		{ 0x06, 0x8217 },
-		{ 0x06, 0xae0f },
-		{ 0x06, 0xa544 },
-		{ 0x06, 0x4402 },
-		{ 0x06, 0xae4d },
-		{ 0x06, 0xa5aa },
-		{ 0x06, 0xaa02 },
-		{ 0x06, 0xae47 },
-		{ 0x06, 0xaf82 },
-		{ 0x06, 0x13ee },
-		{ 0x06, 0x834e },
-		{ 0x06, 0x00ee },
-		{ 0x06, 0x834d },
-		{ 0x06, 0x0fee },
-		{ 0x06, 0x834c },
-		{ 0x06, 0x0fee },
-		{ 0x06, 0x834f },
-		{ 0x06, 0x00ee },
-		{ 0x06, 0x8351 },
-		{ 0x06, 0x00ee },
-		{ 0x06, 0x834a },
-		{ 0x06, 0xffee },
-		{ 0x06, 0x834b },
-		{ 0x06, 0xffe0 },
-		{ 0x06, 0x8330 },
-		{ 0x06, 0xe183 },
-		{ 0x06, 0x3158 },
-		{ 0x06, 0xfee4 },
-		{ 0x06, 0xf88a },
-		{ 0x06, 0xe5f8 },
-		{ 0x06, 0x8be0 },
-		{ 0x06, 0x8332 },
-		{ 0x06, 0xe183 },
-		{ 0x06, 0x3359 },
-		{ 0x06, 0x0fe2 },
-		{ 0x06, 0x834d },
-		{ 0x06, 0x0c24 },
-		{ 0x06, 0x5af0 },
-		{ 0x06, 0x1e12 },
-		{ 0x06, 0xe4f8 },
-		{ 0x06, 0x8ce5 },
-		{ 0x06, 0xf88d },
-		{ 0x06, 0xaf82 },
-		{ 0x06, 0x13e0 },
-		{ 0x06, 0x834f },
-		{ 0x06, 0x10e4 },
-		{ 0x06, 0x834f },
-		{ 0x06, 0xe083 },
-		{ 0x06, 0x4e78 },
-		{ 0x06, 0x009f },
-		{ 0x06, 0x0ae0 },
-		{ 0x06, 0x834f },
-		{ 0x06, 0xa010 },
-		{ 0x06, 0xa5ee },
-		{ 0x06, 0x834e },
-		{ 0x06, 0x01e0 },
-		{ 0x06, 0x834e },
-		{ 0x06, 0x7805 },
-		{ 0x06, 0x9e9a },
-		{ 0x06, 0xe083 },
-		{ 0x06, 0x4e78 },
-		{ 0x06, 0x049e },
-		{ 0x06, 0x10e0 },
-		{ 0x06, 0x834e },
-		{ 0x06, 0x7803 },
-		{ 0x06, 0x9e0f },
-		{ 0x06, 0xe083 },
-		{ 0x06, 0x4e78 },
-		{ 0x06, 0x019e },
-		{ 0x06, 0x05ae },
-		{ 0x06, 0x0caf },
-		{ 0x06, 0x81f8 },
-		{ 0x06, 0xaf81 },
-		{ 0x06, 0xa3af },
-		{ 0x06, 0x81dc },
-		{ 0x06, 0xaf82 },
-		{ 0x06, 0x13ee },
-		{ 0x06, 0x8348 },
-		{ 0x06, 0x00ee },
-		{ 0x06, 0x8349 },
-		{ 0x06, 0x00e0 },
-		{ 0x06, 0x8351 },
-		{ 0x06, 0x10e4 },
-		{ 0x06, 0x8351 },
-		{ 0x06, 0x5801 },
-		{ 0x06, 0x9fea },
-		{ 0x06, 0xd000 },
-		{ 0x06, 0xd180 },
-		{ 0x06, 0x1f66 },
-		{ 0x06, 0xe2f8 },
-		{ 0x06, 0xeae3 },
-		{ 0x06, 0xf8eb },
-		{ 0x06, 0x5af8 },
-		{ 0x06, 0x1e20 },
-		{ 0x06, 0xe6f8 },
-		{ 0x06, 0xeae5 },
-		{ 0x06, 0xf8eb },
-		{ 0x06, 0xd302 },
-		{ 0x06, 0xb3fe },
-		{ 0x06, 0xe2f8 },
-		{ 0x06, 0x7cef },
-		{ 0x06, 0x325b },
-		{ 0x06, 0x80e3 },
-		{ 0x06, 0xf87d },
-		{ 0x06, 0x9e03 },
-		{ 0x06, 0x7dff },
-		{ 0x06, 0xff0d },
-		{ 0x06, 0x581c },
-		{ 0x06, 0x551a },
-		{ 0x06, 0x6511 },
-		{ 0x06, 0xa190 },
-		{ 0x06, 0xd3e2 },
-		{ 0x06, 0x8348 },
-		{ 0x06, 0xe383 },
-		{ 0x06, 0x491b },
-		{ 0x06, 0x56ab },
-		{ 0x06, 0x08ef },
-		{ 0x06, 0x56e6 },
-		{ 0x06, 0x8348 },
-		{ 0x06, 0xe783 },
-		{ 0x06, 0x4910 },
-		{ 0x06, 0xd180 },
-		{ 0x06, 0x1f66 },
-		{ 0x06, 0xa004 },
-		{ 0x06, 0xb9e2 },
-		{ 0x06, 0x8348 },
-		{ 0x06, 0xe383 },
-		{ 0x06, 0x49ef },
-		{ 0x06, 0x65e2 },
-		{ 0x06, 0x834a },
-		{ 0x06, 0xe383 },
-		{ 0x06, 0x4b1b },
-		{ 0x06, 0x56aa },
-		{ 0x06, 0x0eef },
-		{ 0x06, 0x56e6 },
-		{ 0x06, 0x834a },
-		{ 0x06, 0xe783 },
-		{ 0x06, 0x4be2 },
-		{ 0x06, 0x834d },
-		{ 0x06, 0xe683 },
-		{ 0x06, 0x4ce0 },
-		{ 0x06, 0x834d },
-		{ 0x06, 0xa000 },
-		{ 0x06, 0x0caf },
-		{ 0x06, 0x81dc },
-		{ 0x06, 0xe083 },
-		{ 0x06, 0x4d10 },
-		{ 0x06, 0xe483 },
-		{ 0x06, 0x4dae },
-		{ 0x06, 0x0480 },
-		{ 0x06, 0xe483 },
-		{ 0x06, 0x4de0 },
-		{ 0x06, 0x834e },
-		{ 0x06, 0x7803 },
-		{ 0x06, 0x9e0b },
-		{ 0x06, 0xe083 },
-		{ 0x06, 0x4e78 },
-		{ 0x06, 0x049e },
-		{ 0x06, 0x04ee },
-		{ 0x06, 0x834e },
-		{ 0x06, 0x02e0 },
-		{ 0x06, 0x8332 },
-		{ 0x06, 0xe183 },
-		{ 0x06, 0x3359 },
-		{ 0x06, 0x0fe2 },
-		{ 0x06, 0x834d },
-		{ 0x06, 0x0c24 },
-		{ 0x06, 0x5af0 },
-		{ 0x06, 0x1e12 },
-		{ 0x06, 0xe4f8 },
-		{ 0x06, 0x8ce5 },
-		{ 0x06, 0xf88d },
-		{ 0x06, 0xe083 },
-		{ 0x06, 0x30e1 },
-		{ 0x06, 0x8331 },
-		{ 0x06, 0x6801 },
-		{ 0x06, 0xe4f8 },
-		{ 0x06, 0x8ae5 },
-		{ 0x06, 0xf88b },
-		{ 0x06, 0xae37 },
-		{ 0x06, 0xee83 },
-		{ 0x06, 0x4e03 },
-		{ 0x06, 0xe083 },
-		{ 0x06, 0x4ce1 },
-		{ 0x06, 0x834d },
-		{ 0x06, 0x1b01 },
-		{ 0x06, 0x9e04 },
-		{ 0x06, 0xaaa1 },
-		{ 0x06, 0xaea8 },
-		{ 0x06, 0xee83 },
-		{ 0x06, 0x4e04 },
-		{ 0x06, 0xee83 },
-		{ 0x06, 0x4f00 },
-		{ 0x06, 0xaeab },
-		{ 0x06, 0xe083 },
-		{ 0x06, 0x4f78 },
-		{ 0x06, 0x039f },
-		{ 0x06, 0x14ee },
-		{ 0x06, 0x834e },
-		{ 0x06, 0x05d2 },
-		{ 0x06, 0x40d6 },
-		{ 0x06, 0x5554 },
-		{ 0x06, 0x0282 },
-		{ 0x06, 0x17d2 },
-		{ 0x06, 0xa0d6 },
-		{ 0x06, 0xba00 },
-		{ 0x06, 0x0282 },
-		{ 0x06, 0x17fe },
-		{ 0x06, 0xfdfc },
-		{ 0x06, 0x05f8 },
-		{ 0x06, 0xe0f8 },
-		{ 0x06, 0x60e1 },
-		{ 0x06, 0xf861 },
-		{ 0x06, 0x6802 },
-		{ 0x06, 0xe4f8 },
-		{ 0x06, 0x60e5 },
-		{ 0x06, 0xf861 },
-		{ 0x06, 0xe0f8 },
-		{ 0x06, 0x48e1 },
-		{ 0x06, 0xf849 },
-		{ 0x06, 0x580f },
-		{ 0x06, 0x1e02 },
-		{ 0x06, 0xe4f8 },
-		{ 0x06, 0x48e5 },
-		{ 0x06, 0xf849 },
-		{ 0x06, 0xd000 },
-		{ 0x06, 0x0282 },
-		{ 0x06, 0x5bbf },
-		{ 0x06, 0x8350 },
-		{ 0x06, 0xef46 },
-		{ 0x06, 0xdc19 },
-		{ 0x06, 0xddd0 },
-		{ 0x06, 0x0102 },
-		{ 0x06, 0x825b },
-		{ 0x06, 0x0282 },
-		{ 0x06, 0x77e0 },
-		{ 0x06, 0xf860 },
-		{ 0x06, 0xe1f8 },
-		{ 0x06, 0x6158 },
-		{ 0x06, 0xfde4 },
-		{ 0x06, 0xf860 },
-		{ 0x06, 0xe5f8 },
-		{ 0x06, 0x61fc },
-		{ 0x06, 0x04f9 },
-		{ 0x06, 0xfafb },
-		{ 0x06, 0xc6bf },
-		{ 0x06, 0xf840 },
-		{ 0x06, 0xbe83 },
-		{ 0x06, 0x50a0 },
-		{ 0x06, 0x0101 },
-		{ 0x06, 0x071b },
-		{ 0x06, 0x89cf },
-		{ 0x06, 0xd208 },
-		{ 0x06, 0xebdb },
-		{ 0x06, 0x19b2 },
-		{ 0x06, 0xfbff },
-		{ 0x06, 0xfefd },
-		{ 0x06, 0x04f8 },
-		{ 0x06, 0xe0f8 },
-		{ 0x06, 0x48e1 },
-		{ 0x06, 0xf849 },
-		{ 0x06, 0x6808 },
-		{ 0x06, 0xe4f8 },
-		{ 0x06, 0x48e5 },
-		{ 0x06, 0xf849 },
-		{ 0x06, 0x58f7 },
-		{ 0x06, 0xe4f8 },
-		{ 0x06, 0x48e5 },
-		{ 0x06, 0xf849 },
-		{ 0x06, 0xfc04 },
-		{ 0x06, 0x4d20 },
-		{ 0x06, 0x0002 },
-		{ 0x06, 0x4e22 },
-		{ 0x06, 0x0002 },
-		{ 0x06, 0x4ddf },
-		{ 0x06, 0xff01 },
-		{ 0x06, 0x4edd },
-		{ 0x06, 0xff01 },
-		{ 0x05, 0x83d4 },
-		{ 0x06, 0x8000 },
-		{ 0x05, 0x83d8 },
-		{ 0x06, 0x8051 },
-		{ 0x02, 0x6010 },
-		{ 0x03, 0xdc00 },
-		{ 0x05, 0xfff6 },
-		{ 0x06, 0x00fc },
-		{ 0x1f, 0x0000 },
+		{ 0x06, 0x5561 },
+
+		/*
+		 * Can not link to 1Gbps with bad cable
+		 * Decrease SNR threshold form 21.07dB to 19.04dB
+		 */
+		{ 0x1f, 0x0001 },
+		{ 0x17, 0x0cc0 },
 
 		{ 0x1f, 0x0000 },
-		{ 0x0d, 0xf880 },
-		{ 0x1f, 0x0000 }
+		{ 0x0d, 0xf880 }
 	};
+	void __iomem *ioaddr = tp->mmio_addr;
+	const struct firmware *fw;
 
 	rtl_phy_write(ioaddr, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0));
 
+	/*
+	 * Rx Error Issue
+	 * Fine Tune Switching regulator parameter
+	 */
 	mdio_write(ioaddr, 0x1f, 0x0002);
 	mdio_plus_minus(ioaddr, 0x0b, 0x0010, 0x00ef);
 	mdio_plus_minus(ioaddr, 0x0c, 0xa200, 0x5d00);
 
-	rtl_phy_write(ioaddr, phy_reg_init_1, ARRAY_SIZE(phy_reg_init_1));
-
 	if (rtl8168d_efuse_read(ioaddr, 0x01) == 0xb1) {
 		static const struct phy_reg phy_reg_init[] = {
 			{ 0x1f, 0x0002 },
@@ -2157,20 +1885,33 @@  static void rtl8168d_1_hw_phy_config(void __iomem *ioaddr)
 		rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
 	}
 
+	/* RSET couple improve */
 	mdio_write(ioaddr, 0x1f, 0x0002);
 	mdio_patch(ioaddr, 0x0d, 0x0300);
 	mdio_patch(ioaddr, 0x0f, 0x0010);
 
+	/* Fine tune PLL performance */
 	mdio_write(ioaddr, 0x1f, 0x0002);
 	mdio_plus_minus(ioaddr, 0x02, 0x0100, 0x0600);
 	mdio_plus_minus(ioaddr, 0x03, 0x0000, 0xe000);
 
-	rtl_phy_write(ioaddr, phy_reg_init_2, ARRAY_SIZE(phy_reg_init_2));
+	mdio_write(ioaddr, 0x1f, 0x0005);
+	mdio_write(ioaddr, 0x05, 0x001b);
+	if (mdio_read(ioaddr, 0x06) == 0xbf00 &&
+	    request_firmware(&fw, FIRMWARE_8168D_1, &tp->pci_dev->dev) == 0) {
+		rtl_phy_write_fw(tp, fw);
+		release_firmware(fw);
+	} else {
+		netif_warn(tp, probe, tp->dev, "unable to apply firmware patch\n");
+	}
+
+	mdio_write(ioaddr, 0x1f, 0x0000);
 }
 
-static void rtl8168d_2_hw_phy_config(void __iomem *ioaddr)
+static void rtl8168d_2_hw_phy_config(struct rtl8169_private *tp)
 {
 	static const struct phy_reg phy_reg_init_0[] = {
+		/* Channel Estimation */
 		{ 0x1f, 0x0001 },
 		{ 0x06, 0x4064 },
 		{ 0x07, 0x2863 },
@@ -2189,324 +1930,28 @@  static void rtl8168d_2_hw_phy_config(void __iomem *ioaddr)
 		{ 0x1a, 0x05ad },
 		{ 0x14, 0x94c0 },
 
+		/*
+		 * Tx Error Issue
+		 * enhance line driver power
+		 */
 		{ 0x1f, 0x0002 },
 		{ 0x06, 0x5561 },
 		{ 0x1f, 0x0005 },
 		{ 0x05, 0x8332 },
-		{ 0x06, 0x5561 }
-	};
-	static const struct phy_reg phy_reg_init_1[] = {
-		{ 0x1f, 0x0005 },
-		{ 0x05, 0xffc2 },
-		{ 0x1f, 0x0005 },
-		{ 0x05, 0x8000 },
-		{ 0x06, 0xf8f9 },
-		{ 0x06, 0xfaee },
-		{ 0x06, 0xf8ea },
-		{ 0x06, 0x00ee },
-		{ 0x06, 0xf8eb },
-		{ 0x06, 0x00e2 },
-		{ 0x06, 0xf87c },
-		{ 0x06, 0xe3f8 },
-		{ 0x06, 0x7da5 },
-		{ 0x06, 0x1111 },
-		{ 0x06, 0x12d2 },
-		{ 0x06, 0x40d6 },
-		{ 0x06, 0x4444 },
-		{ 0x06, 0x0281 },
-		{ 0x06, 0xc6d2 },
-		{ 0x06, 0xa0d6 },
-		{ 0x06, 0xaaaa },
-		{ 0x06, 0x0281 },
-		{ 0x06, 0xc6ae },
-		{ 0x06, 0x0fa5 },
-		{ 0x06, 0x4444 },
-		{ 0x06, 0x02ae },
-		{ 0x06, 0x4da5 },
-		{ 0x06, 0xaaaa },
-		{ 0x06, 0x02ae },
-		{ 0x06, 0x47af },
-		{ 0x06, 0x81c2 },
-		{ 0x06, 0xee83 },
-		{ 0x06, 0x4e00 },
-		{ 0x06, 0xee83 },
-		{ 0x06, 0x4d0f },
-		{ 0x06, 0xee83 },
-		{ 0x06, 0x4c0f },
-		{ 0x06, 0xee83 },
-		{ 0x06, 0x4f00 },
-		{ 0x06, 0xee83 },
-		{ 0x06, 0x5100 },
-		{ 0x06, 0xee83 },
-		{ 0x06, 0x4aff },
-		{ 0x06, 0xee83 },
-		{ 0x06, 0x4bff },
-		{ 0x06, 0xe083 },
-		{ 0x06, 0x30e1 },
-		{ 0x06, 0x8331 },
-		{ 0x06, 0x58fe },
-		{ 0x06, 0xe4f8 },
-		{ 0x06, 0x8ae5 },
-		{ 0x06, 0xf88b },
-		{ 0x06, 0xe083 },
-		{ 0x06, 0x32e1 },
-		{ 0x06, 0x8333 },
-		{ 0x06, 0x590f },
-		{ 0x06, 0xe283 },
-		{ 0x06, 0x4d0c },
-		{ 0x06, 0x245a },
-		{ 0x06, 0xf01e },
-		{ 0x06, 0x12e4 },
-		{ 0x06, 0xf88c },
-		{ 0x06, 0xe5f8 },
-		{ 0x06, 0x8daf },
-		{ 0x06, 0x81c2 },
-		{ 0x06, 0xe083 },
-		{ 0x06, 0x4f10 },
-		{ 0x06, 0xe483 },
-		{ 0x06, 0x4fe0 },
-		{ 0x06, 0x834e },
-		{ 0x06, 0x7800 },
-		{ 0x06, 0x9f0a },
-		{ 0x06, 0xe083 },
-		{ 0x06, 0x4fa0 },
-		{ 0x06, 0x10a5 },
-		{ 0x06, 0xee83 },
-		{ 0x06, 0x4e01 },
-		{ 0x06, 0xe083 },
-		{ 0x06, 0x4e78 },
-		{ 0x06, 0x059e },
-		{ 0x06, 0x9ae0 },
-		{ 0x06, 0x834e },
-		{ 0x06, 0x7804 },
-		{ 0x06, 0x9e10 },
-		{ 0x06, 0xe083 },
-		{ 0x06, 0x4e78 },
-		{ 0x06, 0x039e },
-		{ 0x06, 0x0fe0 },
-		{ 0x06, 0x834e },
-		{ 0x06, 0x7801 },
-		{ 0x06, 0x9e05 },
-		{ 0x06, 0xae0c },
-		{ 0x06, 0xaf81 },
-		{ 0x06, 0xa7af },
-		{ 0x06, 0x8152 },
-		{ 0x06, 0xaf81 },
-		{ 0x06, 0x8baf },
-		{ 0x06, 0x81c2 },
-		{ 0x06, 0xee83 },
-		{ 0x06, 0x4800 },
-		{ 0x06, 0xee83 },
-		{ 0x06, 0x4900 },
-		{ 0x06, 0xe083 },
-		{ 0x06, 0x5110 },
-		{ 0x06, 0xe483 },
-		{ 0x06, 0x5158 },
-		{ 0x06, 0x019f },
-		{ 0x06, 0xead0 },
-		{ 0x06, 0x00d1 },
-		{ 0x06, 0x801f },
-		{ 0x06, 0x66e2 },
-		{ 0x06, 0xf8ea },
-		{ 0x06, 0xe3f8 },
-		{ 0x06, 0xeb5a },
-		{ 0x06, 0xf81e },
-		{ 0x06, 0x20e6 },
-		{ 0x06, 0xf8ea },
-		{ 0x06, 0xe5f8 },
-		{ 0x06, 0xebd3 },
-		{ 0x06, 0x02b3 },
-		{ 0x06, 0xfee2 },
-		{ 0x06, 0xf87c },
-		{ 0x06, 0xef32 },
-		{ 0x06, 0x5b80 },
-		{ 0x06, 0xe3f8 },
-		{ 0x06, 0x7d9e },
-		{ 0x06, 0x037d },
-		{ 0x06, 0xffff },
-		{ 0x06, 0x0d58 },
-		{ 0x06, 0x1c55 },
-		{ 0x06, 0x1a65 },
-		{ 0x06, 0x11a1 },
-		{ 0x06, 0x90d3 },
-		{ 0x06, 0xe283 },
-		{ 0x06, 0x48e3 },
-		{ 0x06, 0x8349 },
-		{ 0x06, 0x1b56 },
-		{ 0x06, 0xab08 },
-		{ 0x06, 0xef56 },
-		{ 0x06, 0xe683 },
-		{ 0x06, 0x48e7 },
-		{ 0x06, 0x8349 },
-		{ 0x06, 0x10d1 },
-		{ 0x06, 0x801f },
-		{ 0x06, 0x66a0 },
-		{ 0x06, 0x04b9 },
-		{ 0x06, 0xe283 },
-		{ 0x06, 0x48e3 },
-		{ 0x06, 0x8349 },
-		{ 0x06, 0xef65 },
-		{ 0x06, 0xe283 },
-		{ 0x06, 0x4ae3 },
-		{ 0x06, 0x834b },
-		{ 0x06, 0x1b56 },
-		{ 0x06, 0xaa0e },
-		{ 0x06, 0xef56 },
-		{ 0x06, 0xe683 },
-		{ 0x06, 0x4ae7 },
-		{ 0x06, 0x834b },
-		{ 0x06, 0xe283 },
-		{ 0x06, 0x4de6 },
-		{ 0x06, 0x834c },
-		{ 0x06, 0xe083 },
-		{ 0x06, 0x4da0 },
-		{ 0x06, 0x000c },
-		{ 0x06, 0xaf81 },
-		{ 0x06, 0x8be0 },
-		{ 0x06, 0x834d },
-		{ 0x06, 0x10e4 },
-		{ 0x06, 0x834d },
-		{ 0x06, 0xae04 },
-		{ 0x06, 0x80e4 },
-		{ 0x06, 0x834d },
-		{ 0x06, 0xe083 },
-		{ 0x06, 0x4e78 },
-		{ 0x06, 0x039e },
-		{ 0x06, 0x0be0 },
-		{ 0x06, 0x834e },
-		{ 0x06, 0x7804 },
-		{ 0x06, 0x9e04 },
-		{ 0x06, 0xee83 },
-		{ 0x06, 0x4e02 },
-		{ 0x06, 0xe083 },
-		{ 0x06, 0x32e1 },
-		{ 0x06, 0x8333 },
-		{ 0x06, 0x590f },
-		{ 0x06, 0xe283 },
-		{ 0x06, 0x4d0c },
-		{ 0x06, 0x245a },
-		{ 0x06, 0xf01e },
-		{ 0x06, 0x12e4 },
-		{ 0x06, 0xf88c },
-		{ 0x06, 0xe5f8 },
-		{ 0x06, 0x8de0 },
-		{ 0x06, 0x8330 },
-		{ 0x06, 0xe183 },
-		{ 0x06, 0x3168 },
-		{ 0x06, 0x01e4 },
-		{ 0x06, 0xf88a },
-		{ 0x06, 0xe5f8 },
-		{ 0x06, 0x8bae },
-		{ 0x06, 0x37ee },
-		{ 0x06, 0x834e },
-		{ 0x06, 0x03e0 },
-		{ 0x06, 0x834c },
-		{ 0x06, 0xe183 },
-		{ 0x06, 0x4d1b },
-		{ 0x06, 0x019e },
-		{ 0x06, 0x04aa },
-		{ 0x06, 0xa1ae },
-		{ 0x06, 0xa8ee },
-		{ 0x06, 0x834e },
-		{ 0x06, 0x04ee },
-		{ 0x06, 0x834f },
-		{ 0x06, 0x00ae },
-		{ 0x06, 0xabe0 },
-		{ 0x06, 0x834f },
-		{ 0x06, 0x7803 },
-		{ 0x06, 0x9f14 },
-		{ 0x06, 0xee83 },
-		{ 0x06, 0x4e05 },
-		{ 0x06, 0xd240 },
-		{ 0x06, 0xd655 },
-		{ 0x06, 0x5402 },
-		{ 0x06, 0x81c6 },
-		{ 0x06, 0xd2a0 },
-		{ 0x06, 0xd6ba },
-		{ 0x06, 0x0002 },
-		{ 0x06, 0x81c6 },
-		{ 0x06, 0xfefd },
-		{ 0x06, 0xfc05 },
-		{ 0x06, 0xf8e0 },
-		{ 0x06, 0xf860 },
-		{ 0x06, 0xe1f8 },
-		{ 0x06, 0x6168 },
-		{ 0x06, 0x02e4 },
-		{ 0x06, 0xf860 },
-		{ 0x06, 0xe5f8 },
-		{ 0x06, 0x61e0 },
-		{ 0x06, 0xf848 },
-		{ 0x06, 0xe1f8 },
-		{ 0x06, 0x4958 },
-		{ 0x06, 0x0f1e },
-		{ 0x06, 0x02e4 },
-		{ 0x06, 0xf848 },
-		{ 0x06, 0xe5f8 },
-		{ 0x06, 0x49d0 },
-		{ 0x06, 0x0002 },
-		{ 0x06, 0x820a },
-		{ 0x06, 0xbf83 },
-		{ 0x06, 0x50ef },
-		{ 0x06, 0x46dc },
-		{ 0x06, 0x19dd },
-		{ 0x06, 0xd001 },
-		{ 0x06, 0x0282 },
-		{ 0x06, 0x0a02 },
-		{ 0x06, 0x8226 },
-		{ 0x06, 0xe0f8 },
-		{ 0x06, 0x60e1 },
-		{ 0x06, 0xf861 },
-		{ 0x06, 0x58fd },
-		{ 0x06, 0xe4f8 },
-		{ 0x06, 0x60e5 },
-		{ 0x06, 0xf861 },
-		{ 0x06, 0xfc04 },
-		{ 0x06, 0xf9fa },
-		{ 0x06, 0xfbc6 },
-		{ 0x06, 0xbff8 },
-		{ 0x06, 0x40be },
-		{ 0x06, 0x8350 },
-		{ 0x06, 0xa001 },
-		{ 0x06, 0x0107 },
-		{ 0x06, 0x1b89 },
-		{ 0x06, 0xcfd2 },
-		{ 0x06, 0x08eb },
-		{ 0x06, 0xdb19 },
-		{ 0x06, 0xb2fb },
-		{ 0x06, 0xfffe },
-		{ 0x06, 0xfd04 },
-		{ 0x06, 0xf8e0 },
-		{ 0x06, 0xf848 },
-		{ 0x06, 0xe1f8 },
-		{ 0x06, 0x4968 },
-		{ 0x06, 0x08e4 },
-		{ 0x06, 0xf848 },
-		{ 0x06, 0xe5f8 },
-		{ 0x06, 0x4958 },
-		{ 0x06, 0xf7e4 },
-		{ 0x06, 0xf848 },
-		{ 0x06, 0xe5f8 },
-		{ 0x06, 0x49fc },
-		{ 0x06, 0x044d },
-		{ 0x06, 0x2000 },
-		{ 0x06, 0x024e },
-		{ 0x06, 0x2200 },
-		{ 0x06, 0x024d },
-		{ 0x06, 0xdfff },
-		{ 0x06, 0x014e },
-		{ 0x06, 0xddff },
-		{ 0x06, 0x0100 },
-		{ 0x05, 0x83d8 },
-		{ 0x06, 0x8000 },
-		{ 0x03, 0xdc00 },
-		{ 0x05, 0xfff6 },
-		{ 0x06, 0x00fc },
-		{ 0x1f, 0x0000 },
+		{ 0x06, 0x5561 },
+
+		/*
+		 * Can not link to 1Gbps with bad cable
+		 * Decrease SNR threshold form 21.07dB to 19.04dB
+		 */
+		{ 0x1f, 0x0001 },
+		{ 0x17, 0x0cc0 },
 
 		{ 0x1f, 0x0000 },
-		{ 0x0d, 0xf880 },
-		{ 0x1f, 0x0000 }
+		{ 0x0d, 0xf880 }
 	};
+	void __iomem *ioaddr = tp->mmio_addr;
+	const struct firmware *fw;
 
 	rtl_phy_write(ioaddr, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0));
 
@@ -2550,17 +1995,26 @@  static void rtl8168d_2_hw_phy_config(void __iomem *ioaddr)
 		rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
 	}
 
+	/* Fine tune PLL performance */
 	mdio_write(ioaddr, 0x1f, 0x0002);
 	mdio_plus_minus(ioaddr, 0x02, 0x0100, 0x0600);
 	mdio_plus_minus(ioaddr, 0x03, 0x0000, 0xe000);
 
-	mdio_write(ioaddr, 0x1f, 0x0001);
-	mdio_write(ioaddr, 0x17, 0x0cc0);
-
+	/* Switching regulator Slew rate */
 	mdio_write(ioaddr, 0x1f, 0x0002);
 	mdio_patch(ioaddr, 0x0f, 0x0017);
 
-	rtl_phy_write(ioaddr, phy_reg_init_1, ARRAY_SIZE(phy_reg_init_1));
+	mdio_write(ioaddr, 0x1f, 0x0005);
+	mdio_write(ioaddr, 0x05, 0x001b);
+	if (mdio_read(ioaddr, 0x06) == 0xb300 &&
+	    request_firmware(&fw, FIRMWARE_8168D_2, &tp->pci_dev->dev) == 0) {
+		rtl_phy_write_fw(tp, fw);
+		release_firmware(fw);
+	} else {
+		netif_warn(tp, probe, tp->dev, "unable to apply firmware patch\n");
+	}
+
+	mdio_write(ioaddr, 0x1f, 0x0000);
 }
 
 static void rtl8168d_3_hw_phy_config(void __iomem *ioaddr)
@@ -2698,10 +2152,10 @@  static void rtl_hw_phy_config(struct net_device *dev)
 		rtl8168cp_2_hw_phy_config(ioaddr);
 		break;
 	case RTL_GIGA_MAC_VER_25:
-		rtl8168d_1_hw_phy_config(ioaddr);
+		rtl8168d_1_hw_phy_config(tp);
 		break;
 	case RTL_GIGA_MAC_VER_26:
-		rtl8168d_2_hw_phy_config(ioaddr);
+		rtl8168d_2_hw_phy_config(tp);
 		break;
 	case RTL_GIGA_MAC_VER_27:
 		rtl8168d_3_hw_phy_config(ioaddr);