r8169: move PHY regs tables to .rodata
[safe/jmp/linux-2.6] / drivers / net / r8169.c
index 93a87aa..5dba9fa 100644 (file)
@@ -115,7 +115,9 @@ enum mac_version {
        RTL_GIGA_MAC_VER_22 = 0x16, // 8168C
        RTL_GIGA_MAC_VER_23 = 0x17, // 8168CP
        RTL_GIGA_MAC_VER_24 = 0x18, // 8168CP
-       RTL_GIGA_MAC_VER_25 = 0x19  // 8168D
+       RTL_GIGA_MAC_VER_25 = 0x19, // 8168D
+       RTL_GIGA_MAC_VER_26 = 0x1a, // 8168D
+       RTL_GIGA_MAC_VER_27 = 0x1b  // 8168DP
 };
 
 #define _R(NAME,MAC,MASK) \
@@ -150,7 +152,9 @@ static const struct {
        _R("RTL8168c/8111c",    RTL_GIGA_MAC_VER_22, 0xff7e1880), // PCI-E
        _R("RTL8168cp/8111cp",  RTL_GIGA_MAC_VER_23, 0xff7e1880), // PCI-E
        _R("RTL8168cp/8111cp",  RTL_GIGA_MAC_VER_24, 0xff7e1880), // PCI-E
-       _R("RTL8168d/8111d",    RTL_GIGA_MAC_VER_25, 0xff7e1880)  // PCI-E
+       _R("RTL8168d/8111d",    RTL_GIGA_MAC_VER_25, 0xff7e1880), // PCI-E
+       _R("RTL8168d/8111d",    RTL_GIGA_MAC_VER_26, 0xff7e1880), // PCI-E
+       _R("RTL8168dp/8111dp",  RTL_GIGA_MAC_VER_27, 0xff7e1880)  // PCI-E
 };
 #undef _R
 
@@ -253,6 +257,13 @@ enum rtl8168_8101_registers {
        DBG_REG                 = 0xd1,
 #define        FIX_NAK_1                       (1 << 4)
 #define        FIX_NAK_2                       (1 << 3)
+       EFUSEAR                 = 0xdc,
+#define        EFUSEAR_FLAG                    0x80000000
+#define        EFUSEAR_WRITE_CMD               0x80000000
+#define        EFUSEAR_READ_CMD                0x00000000
+#define        EFUSEAR_REG_MASK                0x03ff
+#define        EFUSEAR_REG_SHIFT               8
+#define        EFUSEAR_DATA_MASK               0xff
 };
 
 enum rtl_register_content {
@@ -507,7 +518,8 @@ MODULE_LICENSE("GPL");
 MODULE_VERSION(RTL8169_VERSION);
 
 static int rtl8169_open(struct net_device *dev);
-static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
+                                     struct net_device *dev);
 static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance);
 static int rtl8169_init_ring(struct net_device *dev);
 static void rtl_hw_start(struct net_device *dev);
@@ -567,6 +579,14 @@ static void mdio_patch(void __iomem *ioaddr, int reg_addr, int value)
        mdio_write(ioaddr, reg_addr, mdio_read(ioaddr, reg_addr) | value);
 }
 
+static void mdio_plus_minus(void __iomem *ioaddr, int reg_addr, int p, int m)
+{
+       int val;
+
+       val = mdio_read(ioaddr, reg_addr);
+       mdio_write(ioaddr, reg_addr, (val | p) & ~m);
+}
+
 static void rtl_mdio_write(struct net_device *dev, int phy_id, int location,
                           int val)
 {
@@ -650,6 +670,24 @@ static u32 rtl_csi_read(void __iomem *ioaddr, int addr)
        return value;
 }
 
+static u8 rtl8168d_efuse_read(void __iomem *ioaddr, int reg_addr)
+{
+       u8 value = 0xff;
+       unsigned int i;
+
+       RTL_W32(EFUSEAR, (reg_addr & EFUSEAR_REG_MASK) << EFUSEAR_REG_SHIFT);
+
+       for (i = 0; i < 300; i++) {
+               if (RTL_R32(EFUSEAR) & EFUSEAR_FLAG) {
+                       value = RTL_R32(EFUSEAR) & EFUSEAR_DATA_MASK;
+                       break;
+               }
+               udelay(100);
+       }
+
+       return value;
+}
+
 static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr)
 {
        RTL_W16(IntrMask, 0x0000);
@@ -756,7 +794,7 @@ static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
        struct rtl8169_private *tp = netdev_priv(dev);
        void __iomem *ioaddr = tp->mmio_addr;
        unsigned int i;
-       static struct {
+       static const struct {
                u32 opt;
                u16 reg;
                u8  mask;
@@ -991,7 +1029,10 @@ static void rtl8169_vlan_rx_register(struct net_device *dev,
 
        spin_lock_irqsave(&tp->lock, flags);
        tp->vlgrp = grp;
-       if (tp->vlgrp)
+       /*
+        * Do not disable RxVlan on 8110SCd.
+        */
+       if (tp->vlgrp || (tp->mac_version == RTL_GIGA_MAC_VER_05))
                tp->cp_cmd |= RxVlan;
        else
                tp->cp_cmd &= ~RxVlan;
@@ -1236,13 +1277,16 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp,
         *
         * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec
         */
-       const struct {
+       static const struct {
                u32 mask;
                u32 val;
                int mac_version;
        } mac_info[] = {
                /* 8168D family. */
-               { 0x7c800000, 0x28000000,       RTL_GIGA_MAC_VER_25 },
+               { 0x7cf00000, 0x28300000,       RTL_GIGA_MAC_VER_26 },
+               { 0x7cf00000, 0x28100000,       RTL_GIGA_MAC_VER_25 },
+               { 0x7c800000, 0x28800000,       RTL_GIGA_MAC_VER_27 },
+               { 0x7c800000, 0x28000000,       RTL_GIGA_MAC_VER_26 },
 
                /* 8168C family. */
                { 0x7cf00000, 0x3ca00000,       RTL_GIGA_MAC_VER_24 },
@@ -1307,7 +1351,7 @@ struct phy_reg {
        u16 val;
 };
 
-static void rtl_phy_write(void __iomem *ioaddr, struct phy_reg *regs, int len)
+static void rtl_phy_write(void __iomem *ioaddr, const struct phy_reg *regs, int len)
 {
        while (len-- > 0) {
                mdio_write(ioaddr, regs->reg, regs->val);
@@ -1317,7 +1361,7 @@ static void rtl_phy_write(void __iomem *ioaddr, struct phy_reg *regs, int len)
 
 static void rtl8169s_hw_phy_config(void __iomem *ioaddr)
 {
-       struct phy_reg phy_reg_init[] = {
+       static const struct phy_reg phy_reg_init[] = {
                { 0x1f, 0x0001 },
                { 0x06, 0x006e },
                { 0x08, 0x0708 },
@@ -1384,7 +1428,7 @@ static void rtl8169s_hw_phy_config(void __iomem *ioaddr)
 
 static void rtl8169sb_hw_phy_config(void __iomem *ioaddr)
 {
-       struct phy_reg phy_reg_init[] = {
+       static const struct phy_reg phy_reg_init[] = {
                { 0x1f, 0x0002 },
                { 0x01, 0x90d0 },
                { 0x1f, 0x0000 }
@@ -1413,7 +1457,7 @@ static void rtl8169scd_hw_phy_config_quirk(struct rtl8169_private *tp,
 static void rtl8169scd_hw_phy_config(struct rtl8169_private *tp,
                                     void __iomem *ioaddr)
 {
-       struct phy_reg phy_reg_init[] = {
+       static const struct phy_reg phy_reg_init[] = {
                { 0x1f, 0x0001 },
                { 0x04, 0x0000 },
                { 0x03, 0x00a1 },
@@ -1460,7 +1504,7 @@ static void rtl8169scd_hw_phy_config(struct rtl8169_private *tp,
 
 static void rtl8169sce_hw_phy_config(void __iomem *ioaddr)
 {
-       struct phy_reg phy_reg_init[] = {
+       static const struct phy_reg phy_reg_init[] = {
                { 0x1f, 0x0001 },
                { 0x04, 0x0000 },
                { 0x03, 0x00a1 },
@@ -1513,7 +1557,7 @@ static void rtl8169sce_hw_phy_config(void __iomem *ioaddr)
 
 static void rtl8168bb_hw_phy_config(void __iomem *ioaddr)
 {
-       struct phy_reg phy_reg_init[] = {
+       static const struct phy_reg phy_reg_init[] = {
                { 0x10, 0xf41b },
                { 0x1f, 0x0000 }
        };
@@ -1526,7 +1570,7 @@ static void rtl8168bb_hw_phy_config(void __iomem *ioaddr)
 
 static void rtl8168bef_hw_phy_config(void __iomem *ioaddr)
 {
-       struct phy_reg phy_reg_init[] = {
+       static const struct phy_reg phy_reg_init[] = {
                { 0x1f, 0x0001 },
                { 0x10, 0xf41b },
                { 0x1f, 0x0000 }
@@ -1537,7 +1581,7 @@ static void rtl8168bef_hw_phy_config(void __iomem *ioaddr)
 
 static void rtl8168cp_1_hw_phy_config(void __iomem *ioaddr)
 {
-       struct phy_reg phy_reg_init[] = {
+       static const struct phy_reg phy_reg_init[] = {
                { 0x1f, 0x0000 },
                { 0x1d, 0x0f00 },
                { 0x1f, 0x0002 },
@@ -1550,7 +1594,7 @@ static void rtl8168cp_1_hw_phy_config(void __iomem *ioaddr)
 
 static void rtl8168cp_2_hw_phy_config(void __iomem *ioaddr)
 {
-       struct phy_reg phy_reg_init[] = {
+       static const struct phy_reg phy_reg_init[] = {
                { 0x1f, 0x0001 },
                { 0x1d, 0x3d98 },
                { 0x1f, 0x0000 }
@@ -1565,7 +1609,7 @@ static void rtl8168cp_2_hw_phy_config(void __iomem *ioaddr)
 
 static void rtl8168c_1_hw_phy_config(void __iomem *ioaddr)
 {
-       struct phy_reg phy_reg_init[] = {
+       static const struct phy_reg phy_reg_init[] = {
                { 0x1f, 0x0001 },
                { 0x12, 0x2300 },
                { 0x1f, 0x0002 },
@@ -1594,7 +1638,7 @@ static void rtl8168c_1_hw_phy_config(void __iomem *ioaddr)
 
 static void rtl8168c_2_hw_phy_config(void __iomem *ioaddr)
 {
-       struct phy_reg phy_reg_init[] = {
+       static const struct phy_reg phy_reg_init[] = {
                { 0x1f, 0x0001 },
                { 0x12, 0x2300 },
                { 0x03, 0x802f },
@@ -1622,7 +1666,7 @@ static void rtl8168c_2_hw_phy_config(void __iomem *ioaddr)
 
 static void rtl8168c_3_hw_phy_config(void __iomem *ioaddr)
 {
-       struct phy_reg phy_reg_init[] = {
+       static const struct phy_reg phy_reg_init[] = {
                { 0x1f, 0x0001 },
                { 0x12, 0x2300 },
                { 0x1d, 0x3d98 },
@@ -1647,79 +1691,908 @@ static void rtl8168c_4_hw_phy_config(void __iomem *ioaddr)
        rtl8168c_3_hw_phy_config(ioaddr);
 }
 
-static void rtl8168d_hw_phy_config(void __iomem *ioaddr)
+static void rtl8168d_1_hw_phy_config(void __iomem *ioaddr)
 {
-       struct phy_reg phy_reg_init_0[] = {
+       static const struct phy_reg phy_reg_init_0[] = {
                { 0x1f, 0x0001 },
-               { 0x09, 0x2770 },
-               { 0x08, 0x04d0 },
-               { 0x0b, 0xad15 },
-               { 0x0c, 0x5bf0 },
-               { 0x1c, 0xf101 },
+               { 0x06, 0x4064 },
+               { 0x07, 0x2863 },
+               { 0x08, 0x059c },
+               { 0x09, 0x26b4 },
+               { 0x0a, 0x6a19 },
+               { 0x0b, 0xdcc8 },
+               { 0x10, 0xf06d },
+               { 0x14, 0x7f68 },
+               { 0x18, 0x7fd9 },
+               { 0x1c, 0xf0ff },
+               { 0x1d, 0x3d9c },
                { 0x1f, 0x0003 },
-               { 0x14, 0x94d7 },
-               { 0x12, 0xf4d6 },
-               { 0x09, 0xca0f },
-               { 0x1f, 0x0002 },
-               { 0x0b, 0x0b10 },
-               { 0x0c, 0xd1f7 },
-               { 0x1f, 0x0002 },
-               { 0x06, 0x5461 },
+               { 0x12, 0xf49f },
+               { 0x13, 0x070b },
+               { 0x1a, 0x05ad },
+               { 0x14, 0x94c0 }
+       };
+       static const struct phy_reg phy_reg_init_1[] = {
                { 0x1f, 0x0002 },
-               { 0x05, 0x6662 },
+               { 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 },
-               { 0x14, 0x0060 },
+
                { 0x1f, 0x0000 },
-               { 0x0d, 0xf8a0 },
+               { 0x0d, 0xf880 },
+               { 0x1f, 0x0000 }
+       };
+
+       rtl_phy_write(ioaddr, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0));
+
+       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 },
+                       { 0x05, 0x669a },
+                       { 0x1f, 0x0005 },
+                       { 0x05, 0x8330 },
+                       { 0x06, 0x669a },
+                       { 0x1f, 0x0002 }
+               };
+               int val;
+
+               rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+
+               val = mdio_read(ioaddr, 0x0d);
+
+               if ((val & 0x00ff) != 0x006c) {
+                       static const u32 set[] = {
+                               0x0065, 0x0066, 0x0067, 0x0068,
+                               0x0069, 0x006a, 0x006b, 0x006c
+                       };
+                       int i;
+
+                       mdio_write(ioaddr, 0x1f, 0x0002);
+
+                       val &= 0xff00;
+                       for (i = 0; i < ARRAY_SIZE(set); i++)
+                               mdio_write(ioaddr, 0x0d, val | set[i]);
+               }
+       } else {
+               static const struct phy_reg phy_reg_init[] = {
+                       { 0x1f, 0x0002 },
+                       { 0x05, 0x6662 },
+                       { 0x1f, 0x0005 },
+                       { 0x05, 0x8330 },
+                       { 0x06, 0x6662 }
+               };
+
+               rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+       }
+
+       mdio_write(ioaddr, 0x1f, 0x0002);
+       mdio_patch(ioaddr, 0x0d, 0x0300);
+       mdio_patch(ioaddr, 0x0f, 0x0010);
+
+       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));
+}
+
+static void rtl8168d_2_hw_phy_config(void __iomem *ioaddr)
+{
+       static const struct phy_reg phy_reg_init_0[] = {
+               { 0x1f, 0x0001 },
+               { 0x06, 0x4064 },
+               { 0x07, 0x2863 },
+               { 0x08, 0x059c },
+               { 0x09, 0x26b4 },
+               { 0x0a, 0x6a19 },
+               { 0x0b, 0xdcc8 },
+               { 0x10, 0xf06d },
+               { 0x14, 0x7f68 },
+               { 0x18, 0x7fd9 },
+               { 0x1c, 0xf0ff },
+               { 0x1d, 0x3d9c },
+               { 0x1f, 0x0003 },
+               { 0x12, 0xf49f },
+               { 0x13, 0x070b },
+               { 0x1a, 0x05ad },
+               { 0x14, 0x94c0 },
+
+               { 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, 0xffc2 }
+               { 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 },
+
+               { 0x1f, 0x0000 },
+               { 0x0d, 0xf880 },
+               { 0x1f, 0x0000 }
        };
 
        rtl_phy_write(ioaddr, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0));
 
-       if (mdio_read(ioaddr, 0x06) == 0xc400) {
-               struct phy_reg phy_reg_init_1[] = {
+       if (rtl8168d_efuse_read(ioaddr, 0x01) == 0xb1) {
+               static const struct phy_reg phy_reg_init[] = {
+                       { 0x1f, 0x0002 },
+                       { 0x05, 0x669a },
                        { 0x1f, 0x0005 },
-                       { 0x01, 0x0300 },
-                       { 0x1f, 0x0000 },
-                       { 0x11, 0x401c },
-                       { 0x16, 0x4100 },
+                       { 0x05, 0x8330 },
+                       { 0x06, 0x669a },
+
+                       { 0x1f, 0x0002 }
+               };
+               int val;
+
+               rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+
+               val = mdio_read(ioaddr, 0x0d);
+               if ((val & 0x00ff) != 0x006c) {
+                       u32 set[] = {
+                               0x0065, 0x0066, 0x0067, 0x0068,
+                               0x0069, 0x006a, 0x006b, 0x006c
+                       };
+                       int i;
+
+                       mdio_write(ioaddr, 0x1f, 0x0002);
+
+                       val &= 0xff00;
+                       for (i = 0; i < ARRAY_SIZE(set); i++)
+                               mdio_write(ioaddr, 0x0d, val | set[i]);
+               }
+       } else {
+               static const struct phy_reg phy_reg_init[] = {
+                       { 0x1f, 0x0002 },
+                       { 0x05, 0x2642 },
                        { 0x1f, 0x0005 },
-                       { 0x07, 0x0010 },
-                       { 0x05, 0x83dc },
-                       { 0x06, 0x087d },
-                       { 0x05, 0x8300 },
-                       { 0x06, 0x0101 },
-                       { 0x06, 0x05f8 },
-                       { 0x06, 0xf9fa },
-                       { 0x06, 0xfbef },
-                       { 0x06, 0x79e2 },
-                       { 0x06, 0x835f },
-                       { 0x06, 0xe0f8 },
-                       { 0x06, 0x9ae1 },
-                       { 0x06, 0xf89b },
-                       { 0x06, 0xef31 },
-                       { 0x06, 0x3b65 },
-                       { 0x06, 0xaa07 },
-                       { 0x06, 0x81e4 },
-                       { 0x06, 0xf89a },
-                       { 0x06, 0xe5f8 },
-                       { 0x06, 0x9baf },
-                       { 0x06, 0x06ae },
-                       { 0x05, 0x83dc },
-                       { 0x06, 0x8300 },
+                       { 0x05, 0x8330 },
+                       { 0x06, 0x2642 }
                };
 
-               rtl_phy_write(ioaddr, phy_reg_init_1,
-                             ARRAY_SIZE(phy_reg_init_1));
+               rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
        }
 
-       mdio_write(ioaddr, 0x1f, 0x0000);
+       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);
+
+       mdio_write(ioaddr, 0x1f, 0x0002);
+       mdio_patch(ioaddr, 0x0f, 0x0017);
+
+       rtl_phy_write(ioaddr, phy_reg_init_1, ARRAY_SIZE(phy_reg_init_1));
+}
+
+static void rtl8168d_3_hw_phy_config(void __iomem *ioaddr)
+{
+       static const struct phy_reg phy_reg_init[] = {
+               { 0x1f, 0x0002 },
+               { 0x10, 0x0008 },
+               { 0x0d, 0x006c },
+
+               { 0x1f, 0x0000 },
+               { 0x0d, 0xf880 },
+
+               { 0x1f, 0x0001 },
+               { 0x17, 0x0cc0 },
+
+               { 0x1f, 0x0001 },
+               { 0x0b, 0xa4d8 },
+               { 0x09, 0x281c },
+               { 0x07, 0x2883 },
+               { 0x0a, 0x6b35 },
+               { 0x1d, 0x3da4 },
+               { 0x1c, 0xeffd },
+               { 0x14, 0x7f52 },
+               { 0x18, 0x7fc6 },
+               { 0x08, 0x0601 },
+               { 0x06, 0x4063 },
+               { 0x10, 0xf074 },
+               { 0x1f, 0x0003 },
+               { 0x13, 0x0789 },
+               { 0x12, 0xf4bd },
+               { 0x1a, 0x04fd },
+               { 0x14, 0x84b0 },
+               { 0x1f, 0x0000 },
+               { 0x00, 0x9200 },
+
+               { 0x1f, 0x0005 },
+               { 0x01, 0x0340 },
+               { 0x1f, 0x0001 },
+               { 0x04, 0x4000 },
+               { 0x03, 0x1d21 },
+               { 0x02, 0x0c32 },
+               { 0x01, 0x0200 },
+               { 0x00, 0x5554 },
+               { 0x04, 0x4800 },
+               { 0x04, 0x4000 },
+               { 0x04, 0xf000 },
+               { 0x03, 0xdf01 },
+               { 0x02, 0xdf20 },
+               { 0x01, 0x101a },
+               { 0x00, 0xa0ff },
+               { 0x04, 0xf800 },
+               { 0x04, 0xf000 },
+               { 0x1f, 0x0000 },
+
+               { 0x1f, 0x0007 },
+               { 0x1e, 0x0023 },
+               { 0x16, 0x0000 },
+               { 0x1f, 0x0000 }
+       };
+
+       rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
 }
 
 static void rtl8102e_hw_phy_config(void __iomem *ioaddr)
 {
-       struct phy_reg phy_reg_init[] = {
+       static const struct phy_reg phy_reg_init[] = {
                { 0x1f, 0x0003 },
                { 0x08, 0x441d },
                { 0x01, 0x9100 },
@@ -1729,6 +2602,7 @@ static void rtl8102e_hw_phy_config(void __iomem *ioaddr)
        mdio_write(ioaddr, 0x1f, 0x0000);
        mdio_patch(ioaddr, 0x11, 1 << 12);
        mdio_patch(ioaddr, 0x19, 1 << 13);
+       mdio_patch(ioaddr, 0x10, 1 << 15);
 
        rtl_phy_write(ioaddr, phy_reg_init, ARRAY_SIZE(phy_reg_init));
 }
@@ -1790,7 +2664,13 @@ static void rtl_hw_phy_config(struct net_device *dev)
                rtl8168cp_2_hw_phy_config(ioaddr);
                break;
        case RTL_GIGA_MAC_VER_25:
-               rtl8168d_hw_phy_config(ioaddr);
+               rtl8168d_1_hw_phy_config(ioaddr);
+               break;
+       case RTL_GIGA_MAC_VER_26:
+               rtl8168d_2_hw_phy_config(ioaddr);
+               break;
+       case RTL_GIGA_MAC_VER_27:
+               rtl8168d_3_hw_phy_config(ioaddr);
                break;
 
        default:
@@ -1989,8 +2869,6 @@ static int rtl_xmii_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *dat
                return 0;
 
        case SIOCSMIIREG:
-               if (!capable(CAP_NET_ADMIN))
-                       return -EPERM;
                mdio_write(tp->mmio_addr, data->reg_num & 0x1f, data->val_in);
                return 0;
        }
@@ -2322,6 +3200,14 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        }
 
        rtl8169_init_phy(dev, tp);
+
+       /*
+        * Pretend we are using VLANs; This bypasses a nasty bug where
+        * Interrupts stop flowing on high load on 8110SCd controllers.
+        */
+       if (tp->mac_version == RTL_GIGA_MAC_VER_05)
+               RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | RxVlan);
+
        device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL);
 
 out:
@@ -2357,9 +3243,9 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev)
 static void rtl8169_set_rxbufsize(struct rtl8169_private *tp,
                                  struct net_device *dev)
 {
-       unsigned int mtu = dev->mtu;
+       unsigned int max_frame = dev->mtu + VLAN_ETH_HLEN + ETH_FCS_LEN;
 
-       tp->rx_buf_sz = (mtu > RX_BUF_SIZE) ? mtu + ETH_HLEN + 8 : RX_BUF_SIZE;
+       tp->rx_buf_sz = (max_frame > RX_BUF_SIZE) ? max_frame : RX_BUF_SIZE;
 }
 
 static int rtl8169_open(struct net_device *dev)
@@ -2493,12 +3379,12 @@ static u16 rtl_rw_cpluscmd(void __iomem *ioaddr)
 static void rtl_set_rx_max_size(void __iomem *ioaddr, unsigned int rx_buf_sz)
 {
        /* Low hurts. Let's disable the filtering. */
-       RTL_W16(RxMaxSize, rx_buf_sz);
+       RTL_W16(RxMaxSize, rx_buf_sz + 1);
 }
 
 static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version)
 {
-       struct {
+       static const struct {
                u32 mac_version;
                u32 clk;
                u32 val;
@@ -2622,7 +3508,7 @@ struct ephy_info {
        u16 bits;
 };
 
-static void rtl_ephy_init(void __iomem *ioaddr, struct ephy_info *e, int len)
+static void rtl_ephy_init(void __iomem *ioaddr, const struct ephy_info *e, int len)
 {
        u16 w;
 
@@ -2693,7 +3579,7 @@ static void __rtl_hw_start_8168cp(void __iomem *ioaddr, struct pci_dev *pdev)
 
 static void rtl_hw_start_8168cp_1(void __iomem *ioaddr, struct pci_dev *pdev)
 {
-       static struct ephy_info e_info_8168cp[] = {
+       static const struct ephy_info e_info_8168cp[] = {
                { 0x01, 0,      0x0001 },
                { 0x02, 0x0800, 0x1000 },
                { 0x03, 0,      0x0042 },
@@ -2737,7 +3623,7 @@ static void rtl_hw_start_8168cp_3(void __iomem *ioaddr, struct pci_dev *pdev)
 
 static void rtl_hw_start_8168c_1(void __iomem *ioaddr, struct pci_dev *pdev)
 {
-       static struct ephy_info e_info_8168c_1[] = {
+       static const struct ephy_info e_info_8168c_1[] = {
                { 0x02, 0x0800, 0x1000 },
                { 0x03, 0,      0x0002 },
                { 0x06, 0x0080, 0x0000 }
@@ -2754,7 +3640,7 @@ static void rtl_hw_start_8168c_1(void __iomem *ioaddr, struct pci_dev *pdev)
 
 static void rtl_hw_start_8168c_2(void __iomem *ioaddr, struct pci_dev *pdev)
 {
-       static struct ephy_info e_info_8168c_2[] = {
+       static const struct ephy_info e_info_8168c_2[] = {
                { 0x01, 0,      0x0001 },
                { 0x03, 0x0400, 0x0220 }
        };
@@ -2863,6 +3749,8 @@ static void rtl_hw_start_8168(struct net_device *dev)
        break;
 
        case RTL_GIGA_MAC_VER_25:
+       case RTL_GIGA_MAC_VER_26:
+       case RTL_GIGA_MAC_VER_27:
                rtl_hw_start_8168d(ioaddr, pdev);
        break;
 
@@ -2895,7 +3783,7 @@ static void rtl_hw_start_8168(struct net_device *dev)
 
 static void rtl_hw_start_8102e_1(void __iomem *ioaddr, struct pci_dev *pdev)
 {
-       static struct ephy_info e_info_8102e_1[] = {
+       static const struct ephy_info e_info_8102e_1[] = {
                { 0x01, 0, 0x6e65 },
                { 0x02, 0, 0x091f },
                { 0x03, 0, 0xc2f9 },
@@ -3356,7 +4244,8 @@ static inline u32 rtl8169_tso_csum(struct sk_buff *skb, struct net_device *dev)
        return 0;
 }
 
-static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
+                                     struct net_device *dev)
 {
        struct rtl8169_private *tp = netdev_priv(dev);
        unsigned int frags, entry = tp->cur_tx % NUM_TX_DESC;
@@ -3365,7 +4254,6 @@ static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev)
        dma_addr_t mapping;
        u32 status, len;
        u32 opts1;
-       int ret = NETDEV_TX_OK;
 
        if (unlikely(TX_BUFFS_AVAIL(tp) < skb_shinfo(skb)->nr_frags)) {
                if (netif_msg_drv(tp)) {
@@ -3416,14 +4304,12 @@ static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev)
                        netif_wake_queue(dev);
        }
 
-out:
-       return ret;
+       return NETDEV_TX_OK;
 
 err_stop:
        netif_stop_queue(dev);
-       ret = NETDEV_TX_BUSY;
        dev->stats.tx_dropped++;
-       goto out;
+       return NETDEV_TX_BUSY;
 }
 
 static void rtl8169_pcierr_interrupt(struct net_device *dev)
@@ -3557,13 +4443,12 @@ static inline bool rtl8169_try_rx_copy(struct sk_buff **sk_buff,
        if (pkt_size >= rx_copybreak)
                goto out;
 
-       skb = netdev_alloc_skb(tp->dev, pkt_size + NET_IP_ALIGN);
+       skb = netdev_alloc_skb_ip_align(tp->dev, pkt_size);
        if (!skb)
                goto out;
 
        pci_dma_sync_single_for_cpu(tp->pci_dev, addr, pkt_size,
                                    PCI_DMA_FROMDEVICE);
-       skb_reserve(skb, NET_IP_ALIGN);
        skb_copy_from_linear_data(*sk_buff, skb->data, pkt_size);
        *sk_buff = skb;
        done = true;