Loading drivers/net/ethernet/realtek/r8169.c +430 −57 Original line number Diff line number Diff line Loading @@ -42,6 +42,8 @@ #define FIRMWARE_8168E_1 "rtl_nic/rtl8168e-1.fw" #define FIRMWARE_8168E_2 "rtl_nic/rtl8168e-2.fw" #define FIRMWARE_8168E_3 "rtl_nic/rtl8168e-3.fw" #define FIRMWARE_8168F_1 "rtl_nic/rtl8168f-1.fw" #define FIRMWARE_8168F_2 "rtl_nic/rtl8168f-2.fw" #define FIRMWARE_8105E_1 "rtl_nic/rtl8105e-1.fw" #ifdef RTL8169_DEBUG Loading Loading @@ -133,6 +135,8 @@ enum mac_version { RTL_GIGA_MAC_VER_32, RTL_GIGA_MAC_VER_33, RTL_GIGA_MAC_VER_34, RTL_GIGA_MAC_VER_35, RTL_GIGA_MAC_VER_36, RTL_GIGA_MAC_NONE = 0xff, }; Loading @@ -141,84 +145,110 @@ enum rtl_tx_desc_version { RTL_TD_1 = 1, }; #define _R(NAME,TD,FW) \ { .name = NAME, .txd_version = TD, .fw_name = FW } #define JUMBO_1K ETH_DATA_LEN #define JUMBO_4K (4*1024 - ETH_HLEN - 2) #define JUMBO_6K (6*1024 - ETH_HLEN - 2) #define JUMBO_7K (7*1024 - ETH_HLEN - 2) #define JUMBO_9K (9*1024 - ETH_HLEN - 2) #define _R(NAME,TD,FW,SZ,B) { \ .name = NAME, \ .txd_version = TD, \ .fw_name = FW, \ .jumbo_max = SZ, \ .jumbo_tx_csum = B \ } static const struct { const char *name; enum rtl_tx_desc_version txd_version; const char *fw_name; u16 jumbo_max; bool jumbo_tx_csum; } rtl_chip_infos[] = { /* PCI devices. */ [RTL_GIGA_MAC_VER_01] = _R("RTL8169", RTL_TD_0, NULL), _R("RTL8169", RTL_TD_0, NULL, JUMBO_7K, true), [RTL_GIGA_MAC_VER_02] = _R("RTL8169s", RTL_TD_0, NULL), _R("RTL8169s", RTL_TD_0, NULL, JUMBO_7K, true), [RTL_GIGA_MAC_VER_03] = _R("RTL8110s", RTL_TD_0, NULL), _R("RTL8110s", RTL_TD_0, NULL, JUMBO_7K, true), [RTL_GIGA_MAC_VER_04] = _R("RTL8169sb/8110sb", RTL_TD_0, NULL), _R("RTL8169sb/8110sb", RTL_TD_0, NULL, JUMBO_7K, true), [RTL_GIGA_MAC_VER_05] = _R("RTL8169sc/8110sc", RTL_TD_0, NULL), _R("RTL8169sc/8110sc", RTL_TD_0, NULL, JUMBO_7K, true), [RTL_GIGA_MAC_VER_06] = _R("RTL8169sc/8110sc", RTL_TD_0, NULL), _R("RTL8169sc/8110sc", RTL_TD_0, NULL, JUMBO_7K, true), /* PCI-E devices. */ [RTL_GIGA_MAC_VER_07] = _R("RTL8102e", RTL_TD_1, NULL), _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true), [RTL_GIGA_MAC_VER_08] = _R("RTL8102e", RTL_TD_1, NULL), _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true), [RTL_GIGA_MAC_VER_09] = _R("RTL8102e", RTL_TD_1, NULL), _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true), [RTL_GIGA_MAC_VER_10] = _R("RTL8101e", RTL_TD_0, NULL), _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true), [RTL_GIGA_MAC_VER_11] = _R("RTL8168b/8111b", RTL_TD_0, NULL), _R("RTL8168b/8111b", RTL_TD_0, NULL, JUMBO_4K, false), [RTL_GIGA_MAC_VER_12] = _R("RTL8168b/8111b", RTL_TD_0, NULL), _R("RTL8168b/8111b", RTL_TD_0, NULL, JUMBO_4K, false), [RTL_GIGA_MAC_VER_13] = _R("RTL8101e", RTL_TD_0, NULL), _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true), [RTL_GIGA_MAC_VER_14] = _R("RTL8100e", RTL_TD_0, NULL), _R("RTL8100e", RTL_TD_0, NULL, JUMBO_1K, true), [RTL_GIGA_MAC_VER_15] = _R("RTL8100e", RTL_TD_0, NULL), _R("RTL8100e", RTL_TD_0, NULL, JUMBO_1K, true), [RTL_GIGA_MAC_VER_16] = _R("RTL8101e", RTL_TD_0, NULL), _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true), [RTL_GIGA_MAC_VER_17] = _R("RTL8168b/8111b", RTL_TD_0, NULL), _R("RTL8168b/8111b", RTL_TD_1, NULL, JUMBO_4K, false), [RTL_GIGA_MAC_VER_18] = _R("RTL8168cp/8111cp", RTL_TD_1, NULL), _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false), [RTL_GIGA_MAC_VER_19] = _R("RTL8168c/8111c", RTL_TD_1, NULL), _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false), [RTL_GIGA_MAC_VER_20] = _R("RTL8168c/8111c", RTL_TD_1, NULL), _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false), [RTL_GIGA_MAC_VER_21] = _R("RTL8168c/8111c", RTL_TD_1, NULL), _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false), [RTL_GIGA_MAC_VER_22] = _R("RTL8168c/8111c", RTL_TD_1, NULL), _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false), [RTL_GIGA_MAC_VER_23] = _R("RTL8168cp/8111cp", RTL_TD_1, NULL), _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false), [RTL_GIGA_MAC_VER_24] = _R("RTL8168cp/8111cp", RTL_TD_1, NULL), _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false), [RTL_GIGA_MAC_VER_25] = _R("RTL8168d/8111d", RTL_TD_1, FIRMWARE_8168D_1), _R("RTL8168d/8111d", RTL_TD_1, FIRMWARE_8168D_1, JUMBO_9K, false), [RTL_GIGA_MAC_VER_26] = _R("RTL8168d/8111d", RTL_TD_1, FIRMWARE_8168D_2), _R("RTL8168d/8111d", RTL_TD_1, FIRMWARE_8168D_2, JUMBO_9K, false), [RTL_GIGA_MAC_VER_27] = _R("RTL8168dp/8111dp", RTL_TD_1, NULL), _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false), [RTL_GIGA_MAC_VER_28] = _R("RTL8168dp/8111dp", RTL_TD_1, NULL), _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false), [RTL_GIGA_MAC_VER_29] = _R("RTL8105e", RTL_TD_1, FIRMWARE_8105E_1), _R("RTL8105e", RTL_TD_1, FIRMWARE_8105E_1, JUMBO_1K, true), [RTL_GIGA_MAC_VER_30] = _R("RTL8105e", RTL_TD_1, FIRMWARE_8105E_1), _R("RTL8105e", RTL_TD_1, FIRMWARE_8105E_1, JUMBO_1K, true), [RTL_GIGA_MAC_VER_31] = _R("RTL8168dp/8111dp", RTL_TD_1, NULL), _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false), [RTL_GIGA_MAC_VER_32] = _R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_1), _R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_1, JUMBO_9K, false), [RTL_GIGA_MAC_VER_33] = _R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_2), _R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_2, JUMBO_9K, false), [RTL_GIGA_MAC_VER_34] = _R("RTL8168evl/8111evl",RTL_TD_1, FIRMWARE_8168E_3) _R("RTL8168evl/8111evl",RTL_TD_1, FIRMWARE_8168E_3, JUMBO_9K, false), [RTL_GIGA_MAC_VER_35] = _R("RTL8168f/8111f", RTL_TD_1, FIRMWARE_8168F_1, JUMBO_9K, false), [RTL_GIGA_MAC_VER_36] = _R("RTL8168f/8111f", RTL_TD_1, FIRMWARE_8168F_2, JUMBO_9K, false), }; #undef _R Loading Loading @@ -311,6 +341,7 @@ enum rtl_registers { MaxTxPacketSize = 0xec, /* 8101/8168. Unit of 128 bytes. */ #define TxPacketMax (8064 >> 7) #define EarlySize 0x27 FuncEvent = 0xf0, FuncEventMask = 0xf4, Loading Loading @@ -460,8 +491,12 @@ enum rtl_register_content { /* Config3 register p.25 */ MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */ LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */ Jumbo_En0 = (1 << 2), /* 8168 only. Reserved in the 8168b */ Beacon_en = (1 << 0), /* 8168 only. Reserved in the 8168b */ /* Config4 register */ Jumbo_En1 = (1 << 1), /* 8168 only. Reserved in the 8168b */ /* Config5 register p.27 */ BWF = (1 << 6), /* Accept Broadcast wakeup frame */ MWF = (1 << 5), /* Accept Multicast wakeup frame */ Loading Loading @@ -670,6 +705,11 @@ struct rtl8169_private { void (*up)(struct rtl8169_private *); } pll_power_ops; struct jumbo_ops { void (*enable)(struct rtl8169_private *); void (*disable)(struct rtl8169_private *); } jumbo_ops; int (*set_speed)(struct net_device *, u8 aneg, u16 sp, u8 dpx, u32 adv); int (*get_settings)(struct net_device *, struct ethtool_cmd *); void (*phy_reset_enable)(struct rtl8169_private *tp); Loading Loading @@ -714,6 +754,8 @@ MODULE_FIRMWARE(FIRMWARE_8168E_1); MODULE_FIRMWARE(FIRMWARE_8168E_2); MODULE_FIRMWARE(FIRMWARE_8168E_3); MODULE_FIRMWARE(FIRMWARE_8105E_1); MODULE_FIRMWARE(FIRMWARE_8168F_1); MODULE_FIRMWARE(FIRMWARE_8168F_2); static int rtl8169_open(struct net_device *dev); static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, Loading @@ -732,6 +774,19 @@ static void rtl8169_down(struct net_device *dev); static void rtl8169_rx_clear(struct rtl8169_private *tp); static int rtl8169_poll(struct napi_struct *napi, int budget); static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force) { int cap = pci_pcie_cap(pdev); if (cap) { u16 ctl; pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl); ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | force; pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl); } } static u32 ocp_read(struct rtl8169_private *tp, u8 mask, u16 reg) { void __iomem *ioaddr = tp->mmio_addr; Loading Loading @@ -1202,6 +1257,19 @@ static void rtl_link_chg_patch(struct rtl8169_private *tp) ERIAR_EXGMAC); rtl_w1w0_eri(ioaddr, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC); } else if (tp->mac_version == RTL_GIGA_MAC_VER_35 || tp->mac_version == RTL_GIGA_MAC_VER_36) { if (RTL_R8(PHYstatus) & _1000bpsF) { rtl_eri_write(ioaddr, 0x1bc, ERIAR_MASK_1111, 0x00000011, ERIAR_EXGMAC); rtl_eri_write(ioaddr, 0x1dc, ERIAR_MASK_1111, 0x00000005, ERIAR_EXGMAC); } else { rtl_eri_write(ioaddr, 0x1bc, ERIAR_MASK_1111, 0x0000001f, ERIAR_EXGMAC); rtl_eri_write(ioaddr, 0x1dc, ERIAR_MASK_1111, 0x0000003f, ERIAR_EXGMAC); } } } Loading Loading @@ -1487,9 +1555,15 @@ static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) static u32 rtl8169_fix_features(struct net_device *dev, u32 features) { struct rtl8169_private *tp = netdev_priv(dev); if (dev->mtu > TD_MSS_MAX) features &= ~NETIF_F_ALL_TSO; if (dev->mtu > JUMBO_1K && !rtl_chip_infos[tp->mac_version].jumbo_tx_csum) features &= ~NETIF_F_IP_CSUM; return features; } Loading Loading @@ -1741,6 +1815,10 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp, u32 val; int mac_version; } mac_info[] = { /* 8168F family. */ { 0x7cf00000, 0x48100000, RTL_GIGA_MAC_VER_36 }, { 0x7cf00000, 0x48000000, RTL_GIGA_MAC_VER_35 }, /* 8168E family. */ { 0x7c800000, 0x2c800000, RTL_GIGA_MAC_VER_34 }, { 0x7cf00000, 0x2c200000, RTL_GIGA_MAC_VER_33 }, Loading Loading @@ -2875,6 +2953,97 @@ static void rtl8168e_2_hw_phy_config(struct rtl8169_private *tp) rtl_writephy(tp, 0x1f, 0x0000); } static void rtl8168f_1_hw_phy_config(struct rtl8169_private *tp) { static const struct phy_reg phy_reg_init[] = { /* Channel estimation fine tune */ { 0x1f, 0x0003 }, { 0x09, 0xa20f }, { 0x1f, 0x0000 }, /* Modify green table for giga & fnet */ { 0x1f, 0x0005 }, { 0x05, 0x8b55 }, { 0x06, 0x0000 }, { 0x05, 0x8b5e }, { 0x06, 0x0000 }, { 0x05, 0x8b67 }, { 0x06, 0x0000 }, { 0x05, 0x8b70 }, { 0x06, 0x0000 }, { 0x1f, 0x0000 }, { 0x1f, 0x0007 }, { 0x1e, 0x0078 }, { 0x17, 0x0000 }, { 0x19, 0x00fb }, { 0x1f, 0x0000 }, /* Modify green table for 10M */ { 0x1f, 0x0005 }, { 0x05, 0x8b79 }, { 0x06, 0xaa00 }, { 0x1f, 0x0000 }, /* Disable hiimpedance detection (RTCT) */ { 0x1f, 0x0003 }, { 0x01, 0x328a }, { 0x1f, 0x0000 } }; rtl_apply_firmware(tp); rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); /* For 4-corner performance improve */ rtl_writephy(tp, 0x1f, 0x0005); rtl_writephy(tp, 0x05, 0x8b80); rtl_w1w0_phy(tp, 0x06, 0x0006, 0x0000); rtl_writephy(tp, 0x1f, 0x0000); /* PHY auto speed down */ rtl_writephy(tp, 0x1f, 0x0007); rtl_writephy(tp, 0x1e, 0x002d); rtl_w1w0_phy(tp, 0x18, 0x0010, 0x0000); rtl_writephy(tp, 0x1f, 0x0000); rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000); /* Improve 10M EEE waveform */ rtl_writephy(tp, 0x1f, 0x0005); rtl_writephy(tp, 0x05, 0x8b86); rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000); rtl_writephy(tp, 0x1f, 0x0000); /* Improve 2-pair detection performance */ rtl_writephy(tp, 0x1f, 0x0005); rtl_writephy(tp, 0x05, 0x8b85); rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000); rtl_writephy(tp, 0x1f, 0x0000); } static void rtl8168f_2_hw_phy_config(struct rtl8169_private *tp) { rtl_apply_firmware(tp); /* For 4-corner performance improve */ rtl_writephy(tp, 0x1f, 0x0005); rtl_writephy(tp, 0x05, 0x8b80); rtl_w1w0_phy(tp, 0x06, 0x0006, 0x0000); rtl_writephy(tp, 0x1f, 0x0000); /* PHY auto speed down */ rtl_writephy(tp, 0x1f, 0x0007); rtl_writephy(tp, 0x1e, 0x002d); rtl_w1w0_phy(tp, 0x18, 0x0010, 0x0000); rtl_writephy(tp, 0x1f, 0x0000); rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000); /* Improve 10M EEE waveform */ rtl_writephy(tp, 0x1f, 0x0005); rtl_writephy(tp, 0x05, 0x8b86); rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000); rtl_writephy(tp, 0x1f, 0x0000); } static void rtl8102e_hw_phy_config(struct rtl8169_private *tp) { static const struct phy_reg phy_reg_init[] = { Loading Loading @@ -2999,6 +3168,12 @@ static void rtl_hw_phy_config(struct net_device *dev) case RTL_GIGA_MAC_VER_34: rtl8168e_2_hw_phy_config(tp); break; case RTL_GIGA_MAC_VER_35: rtl8168f_1_hw_phy_config(tp); break; case RTL_GIGA_MAC_VER_36: rtl8168f_2_hw_phy_config(tp); break; default: break; Loading Loading @@ -3483,7 +3658,7 @@ static void r8168_pll_power_up(struct rtl8169_private *tp) r8168_phy_power_up(tp); } static void rtl_pll_power_op(struct rtl8169_private *tp, static void rtl_generic_op(struct rtl8169_private *tp, void (*op)(struct rtl8169_private *)) { if (op) Loading @@ -3492,12 +3667,12 @@ static void rtl_pll_power_op(struct rtl8169_private *tp, static void rtl_pll_power_down(struct rtl8169_private *tp) { rtl_pll_power_op(tp, tp->pll_power_ops.down); rtl_generic_op(tp, tp->pll_power_ops.down); } static void rtl_pll_power_up(struct rtl8169_private *tp) { rtl_pll_power_op(tp, tp->pll_power_ops.up); rtl_generic_op(tp, tp->pll_power_ops.up); } static void __devinit rtl_init_pll_power_ops(struct rtl8169_private *tp) Loading Loading @@ -3534,6 +3709,8 @@ static void __devinit rtl_init_pll_power_ops(struct rtl8169_private *tp) case RTL_GIGA_MAC_VER_32: case RTL_GIGA_MAC_VER_33: case RTL_GIGA_MAC_VER_34: case RTL_GIGA_MAC_VER_35: case RTL_GIGA_MAC_VER_36: ops->down = r8168_pll_power_down; ops->up = r8168_pll_power_up; break; Loading Loading @@ -3586,6 +3763,150 @@ static void rtl8169_init_ring_indexes(struct rtl8169_private *tp) tp->dirty_tx = tp->dirty_rx = tp->cur_tx = tp->cur_rx = 0; } static void rtl_hw_jumbo_enable(struct rtl8169_private *tp) { rtl_generic_op(tp, tp->jumbo_ops.enable); } static void rtl_hw_jumbo_disable(struct rtl8169_private *tp) { rtl_generic_op(tp, tp->jumbo_ops.disable); } static void r8168c_hw_jumbo_enable(struct rtl8169_private *tp) { void __iomem *ioaddr = tp->mmio_addr; RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0); RTL_W8(Config4, RTL_R8(Config4) | Jumbo_En1); rtl_tx_performance_tweak(tp->pci_dev, 0x2 << MAX_READ_REQUEST_SHIFT); } static void r8168c_hw_jumbo_disable(struct rtl8169_private *tp) { void __iomem *ioaddr = tp->mmio_addr; RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0); RTL_W8(Config4, RTL_R8(Config4) & ~Jumbo_En1); rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT); } static void r8168dp_hw_jumbo_enable(struct rtl8169_private *tp) { void __iomem *ioaddr = tp->mmio_addr; RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0); } static void r8168dp_hw_jumbo_disable(struct rtl8169_private *tp) { void __iomem *ioaddr = tp->mmio_addr; RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0); } static void r8168e_hw_jumbo_enable(struct rtl8169_private *tp) { void __iomem *ioaddr = tp->mmio_addr; struct pci_dev *pdev = tp->pci_dev; RTL_W8(MaxTxPacketSize, 0x3f); RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0); RTL_W8(Config4, RTL_R8(Config4) | 0x01); pci_write_config_byte(pdev, 0x79, 0x20); } static void r8168e_hw_jumbo_disable(struct rtl8169_private *tp) { void __iomem *ioaddr = tp->mmio_addr; struct pci_dev *pdev = tp->pci_dev; RTL_W8(MaxTxPacketSize, 0x0c); RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0); RTL_W8(Config4, RTL_R8(Config4) & ~0x01); pci_write_config_byte(pdev, 0x79, 0x50); } static void r8168b_0_hw_jumbo_enable(struct rtl8169_private *tp) { rtl_tx_performance_tweak(tp->pci_dev, (0x2 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN); } static void r8168b_0_hw_jumbo_disable(struct rtl8169_private *tp) { rtl_tx_performance_tweak(tp->pci_dev, (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN); } static void r8168b_1_hw_jumbo_enable(struct rtl8169_private *tp) { void __iomem *ioaddr = tp->mmio_addr; r8168b_0_hw_jumbo_enable(tp); RTL_W8(Config4, RTL_R8(Config4) | (1 << 0)); } static void r8168b_1_hw_jumbo_disable(struct rtl8169_private *tp) { void __iomem *ioaddr = tp->mmio_addr; r8168b_0_hw_jumbo_disable(tp); RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0)); } static void __devinit rtl_init_jumbo_ops(struct rtl8169_private *tp) { struct jumbo_ops *ops = &tp->jumbo_ops; switch (tp->mac_version) { case RTL_GIGA_MAC_VER_11: ops->disable = r8168b_0_hw_jumbo_disable; ops->enable = r8168b_0_hw_jumbo_enable; break; case RTL_GIGA_MAC_VER_12: case RTL_GIGA_MAC_VER_17: ops->disable = r8168b_1_hw_jumbo_disable; ops->enable = r8168b_1_hw_jumbo_enable; break; case RTL_GIGA_MAC_VER_18: /* Wild guess. Needs info from Realtek. */ case RTL_GIGA_MAC_VER_19: case RTL_GIGA_MAC_VER_20: case RTL_GIGA_MAC_VER_21: /* Wild guess. Needs info from Realtek. */ case RTL_GIGA_MAC_VER_22: case RTL_GIGA_MAC_VER_23: case RTL_GIGA_MAC_VER_24: case RTL_GIGA_MAC_VER_25: case RTL_GIGA_MAC_VER_26: ops->disable = r8168c_hw_jumbo_disable; ops->enable = r8168c_hw_jumbo_enable; break; case RTL_GIGA_MAC_VER_27: case RTL_GIGA_MAC_VER_28: ops->disable = r8168dp_hw_jumbo_disable; ops->enable = r8168dp_hw_jumbo_enable; break; case RTL_GIGA_MAC_VER_31: /* Wild guess. Needs info from Realtek. */ case RTL_GIGA_MAC_VER_32: case RTL_GIGA_MAC_VER_33: case RTL_GIGA_MAC_VER_34: ops->disable = r8168e_hw_jumbo_disable; ops->enable = r8168e_hw_jumbo_enable; break; /* * No action needed for jumbo frames with 8169. * No jumbo for 810x at all. */ default: ops->disable = NULL; ops->enable = NULL; break; } } static void rtl_hw_reset(struct rtl8169_private *tp) { void __iomem *ioaddr = tp->mmio_addr; Loading Loading @@ -3730,6 +4051,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) rtl_init_mdio_ops(tp); rtl_init_pll_power_ops(tp); rtl_init_jumbo_ops(tp); rtl8169_print_mac_version(tp); Loading Loading @@ -3813,6 +4135,12 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) netif_info(tp, probe, dev, "%s at 0x%lx, %pM, XID %08x IRQ %d\n", rtl_chip_infos[chipset].name, dev->base_addr, dev->dev_addr, (u32)(RTL_R32(TxConfig) & 0x9cf0f8ff), dev->irq); if (rtl_chip_infos[chipset].jumbo_max != JUMBO_1K) { netif_info(tp, probe, dev, "jumbo features [frames: %d bytes, " "tx checksumming: %s]\n", rtl_chip_infos[chipset].jumbo_max, rtl_chip_infos[chipset].jumbo_tx_csum ? "ok" : "ko"); } if (tp->mac_version == RTL_GIGA_MAC_VER_27 || tp->mac_version == RTL_GIGA_MAC_VER_28 || Loading Loading @@ -4008,7 +4336,9 @@ static void rtl8169_hw_reset(struct rtl8169_private *tp) tp->mac_version == RTL_GIGA_MAC_VER_31) { while (RTL_R8(TxPoll) & NPQ) udelay(20); } else if (tp->mac_version == RTL_GIGA_MAC_VER_34) { } else if (tp->mac_version == RTL_GIGA_MAC_VER_34 || tp->mac_version == RTL_GIGA_MAC_VER_35 || tp->mac_version == RTL_GIGA_MAC_VER_36) { RTL_W8(ChipCmd, RTL_R8(ChipCmd) | StopReq); while (!(RTL_R32(TxConfig) & TXCFG_EMPTY)) udelay(100); Loading Loading @@ -4167,19 +4497,6 @@ static void rtl_hw_start_8169(struct net_device *dev) RTL_W16(IntrMask, tp->intr_event); } static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force) { int cap = pci_pcie_cap(pdev); if (cap) { u16 ctl; pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl); ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | force; pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl); } } static void rtl_csi_access_enable(void __iomem *ioaddr, u32 bits) { u32 csi; Loading Loading @@ -4479,7 +4796,50 @@ static void rtl_hw_start_8168e_2(void __iomem *ioaddr, struct pci_dev *pdev) rtl_w1w0_eri(ioaddr, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0xff00, ERIAR_EXGMAC); RTL_W8(MaxTxPacketSize, 0x27); RTL_W8(MaxTxPacketSize, EarlySize); rtl_disable_clock_request(pdev); RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO); RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB); /* Adjust EEE LED frequency */ RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07); RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN); RTL_W32(MISC, RTL_R32(MISC) | PWM_EN); RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en); } static void rtl_hw_start_8168f_1(void __iomem *ioaddr, struct pci_dev *pdev) { static const struct ephy_info e_info_8168f_1[] = { { 0x06, 0x00c0, 0x0020 }, { 0x08, 0x0001, 0x0002 }, { 0x09, 0x0000, 0x0080 }, { 0x19, 0x0000, 0x0224 } }; rtl_csi_access_enable_1(ioaddr); rtl_ephy_init(ioaddr, e_info_8168f_1, ARRAY_SIZE(e_info_8168f_1)); rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); rtl_eri_write(ioaddr, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); rtl_eri_write(ioaddr, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); rtl_eri_write(ioaddr, 0xc8, ERIAR_MASK_1111, 0x00100002, ERIAR_EXGMAC); rtl_eri_write(ioaddr, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC); rtl_w1w0_eri(ioaddr, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC); rtl_w1w0_eri(ioaddr, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC); rtl_w1w0_eri(ioaddr, 0x1b0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC); rtl_w1w0_eri(ioaddr, 0x1d0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC); rtl_eri_write(ioaddr, 0xcc, ERIAR_MASK_1111, 0x00000050, ERIAR_EXGMAC); rtl_eri_write(ioaddr, 0xd0, ERIAR_MASK_1111, 0x00000060, ERIAR_EXGMAC); rtl_w1w0_eri(ioaddr, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0xff00, ERIAR_EXGMAC); RTL_W8(MaxTxPacketSize, EarlySize); rtl_disable_clock_request(pdev); Loading Loading @@ -4588,6 +4948,11 @@ static void rtl_hw_start_8168(struct net_device *dev) rtl_hw_start_8168e_2(ioaddr, pdev); break; case RTL_GIGA_MAC_VER_35: case RTL_GIGA_MAC_VER_36: rtl_hw_start_8168f_1(ioaddr, pdev); break; default: printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n", dev->name, tp->mac_version); Loading Loading @@ -4759,9 +5124,17 @@ static void rtl_hw_start_8101(struct net_device *dev) static int rtl8169_change_mtu(struct net_device *dev, int new_mtu) { if (new_mtu < ETH_ZLEN || new_mtu > SafeMtu) struct rtl8169_private *tp = netdev_priv(dev); if (new_mtu < ETH_ZLEN || new_mtu > rtl_chip_infos[tp->mac_version].jumbo_max) return -EINVAL; if (new_mtu > ETH_DATA_LEN) rtl_hw_jumbo_enable(tp); else rtl_hw_jumbo_disable(tp); dev->mtu = new_mtu; netdev_update_features(dev); Loading Loading @@ -5356,7 +5729,7 @@ static int rtl8169_rx_interrupt(struct net_device *dev, } else { struct sk_buff *skb; dma_addr_t addr = le64_to_cpu(desc->addr); int pkt_size = (status & 0x00001FFF) - 4; int pkt_size = (status & 0x00003fff) - 4; /* * The driver does not support incoming fragmented Loading Loading
drivers/net/ethernet/realtek/r8169.c +430 −57 Original line number Diff line number Diff line Loading @@ -42,6 +42,8 @@ #define FIRMWARE_8168E_1 "rtl_nic/rtl8168e-1.fw" #define FIRMWARE_8168E_2 "rtl_nic/rtl8168e-2.fw" #define FIRMWARE_8168E_3 "rtl_nic/rtl8168e-3.fw" #define FIRMWARE_8168F_1 "rtl_nic/rtl8168f-1.fw" #define FIRMWARE_8168F_2 "rtl_nic/rtl8168f-2.fw" #define FIRMWARE_8105E_1 "rtl_nic/rtl8105e-1.fw" #ifdef RTL8169_DEBUG Loading Loading @@ -133,6 +135,8 @@ enum mac_version { RTL_GIGA_MAC_VER_32, RTL_GIGA_MAC_VER_33, RTL_GIGA_MAC_VER_34, RTL_GIGA_MAC_VER_35, RTL_GIGA_MAC_VER_36, RTL_GIGA_MAC_NONE = 0xff, }; Loading @@ -141,84 +145,110 @@ enum rtl_tx_desc_version { RTL_TD_1 = 1, }; #define _R(NAME,TD,FW) \ { .name = NAME, .txd_version = TD, .fw_name = FW } #define JUMBO_1K ETH_DATA_LEN #define JUMBO_4K (4*1024 - ETH_HLEN - 2) #define JUMBO_6K (6*1024 - ETH_HLEN - 2) #define JUMBO_7K (7*1024 - ETH_HLEN - 2) #define JUMBO_9K (9*1024 - ETH_HLEN - 2) #define _R(NAME,TD,FW,SZ,B) { \ .name = NAME, \ .txd_version = TD, \ .fw_name = FW, \ .jumbo_max = SZ, \ .jumbo_tx_csum = B \ } static const struct { const char *name; enum rtl_tx_desc_version txd_version; const char *fw_name; u16 jumbo_max; bool jumbo_tx_csum; } rtl_chip_infos[] = { /* PCI devices. */ [RTL_GIGA_MAC_VER_01] = _R("RTL8169", RTL_TD_0, NULL), _R("RTL8169", RTL_TD_0, NULL, JUMBO_7K, true), [RTL_GIGA_MAC_VER_02] = _R("RTL8169s", RTL_TD_0, NULL), _R("RTL8169s", RTL_TD_0, NULL, JUMBO_7K, true), [RTL_GIGA_MAC_VER_03] = _R("RTL8110s", RTL_TD_0, NULL), _R("RTL8110s", RTL_TD_0, NULL, JUMBO_7K, true), [RTL_GIGA_MAC_VER_04] = _R("RTL8169sb/8110sb", RTL_TD_0, NULL), _R("RTL8169sb/8110sb", RTL_TD_0, NULL, JUMBO_7K, true), [RTL_GIGA_MAC_VER_05] = _R("RTL8169sc/8110sc", RTL_TD_0, NULL), _R("RTL8169sc/8110sc", RTL_TD_0, NULL, JUMBO_7K, true), [RTL_GIGA_MAC_VER_06] = _R("RTL8169sc/8110sc", RTL_TD_0, NULL), _R("RTL8169sc/8110sc", RTL_TD_0, NULL, JUMBO_7K, true), /* PCI-E devices. */ [RTL_GIGA_MAC_VER_07] = _R("RTL8102e", RTL_TD_1, NULL), _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true), [RTL_GIGA_MAC_VER_08] = _R("RTL8102e", RTL_TD_1, NULL), _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true), [RTL_GIGA_MAC_VER_09] = _R("RTL8102e", RTL_TD_1, NULL), _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true), [RTL_GIGA_MAC_VER_10] = _R("RTL8101e", RTL_TD_0, NULL), _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true), [RTL_GIGA_MAC_VER_11] = _R("RTL8168b/8111b", RTL_TD_0, NULL), _R("RTL8168b/8111b", RTL_TD_0, NULL, JUMBO_4K, false), [RTL_GIGA_MAC_VER_12] = _R("RTL8168b/8111b", RTL_TD_0, NULL), _R("RTL8168b/8111b", RTL_TD_0, NULL, JUMBO_4K, false), [RTL_GIGA_MAC_VER_13] = _R("RTL8101e", RTL_TD_0, NULL), _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true), [RTL_GIGA_MAC_VER_14] = _R("RTL8100e", RTL_TD_0, NULL), _R("RTL8100e", RTL_TD_0, NULL, JUMBO_1K, true), [RTL_GIGA_MAC_VER_15] = _R("RTL8100e", RTL_TD_0, NULL), _R("RTL8100e", RTL_TD_0, NULL, JUMBO_1K, true), [RTL_GIGA_MAC_VER_16] = _R("RTL8101e", RTL_TD_0, NULL), _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true), [RTL_GIGA_MAC_VER_17] = _R("RTL8168b/8111b", RTL_TD_0, NULL), _R("RTL8168b/8111b", RTL_TD_1, NULL, JUMBO_4K, false), [RTL_GIGA_MAC_VER_18] = _R("RTL8168cp/8111cp", RTL_TD_1, NULL), _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false), [RTL_GIGA_MAC_VER_19] = _R("RTL8168c/8111c", RTL_TD_1, NULL), _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false), [RTL_GIGA_MAC_VER_20] = _R("RTL8168c/8111c", RTL_TD_1, NULL), _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false), [RTL_GIGA_MAC_VER_21] = _R("RTL8168c/8111c", RTL_TD_1, NULL), _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false), [RTL_GIGA_MAC_VER_22] = _R("RTL8168c/8111c", RTL_TD_1, NULL), _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false), [RTL_GIGA_MAC_VER_23] = _R("RTL8168cp/8111cp", RTL_TD_1, NULL), _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false), [RTL_GIGA_MAC_VER_24] = _R("RTL8168cp/8111cp", RTL_TD_1, NULL), _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false), [RTL_GIGA_MAC_VER_25] = _R("RTL8168d/8111d", RTL_TD_1, FIRMWARE_8168D_1), _R("RTL8168d/8111d", RTL_TD_1, FIRMWARE_8168D_1, JUMBO_9K, false), [RTL_GIGA_MAC_VER_26] = _R("RTL8168d/8111d", RTL_TD_1, FIRMWARE_8168D_2), _R("RTL8168d/8111d", RTL_TD_1, FIRMWARE_8168D_2, JUMBO_9K, false), [RTL_GIGA_MAC_VER_27] = _R("RTL8168dp/8111dp", RTL_TD_1, NULL), _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false), [RTL_GIGA_MAC_VER_28] = _R("RTL8168dp/8111dp", RTL_TD_1, NULL), _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false), [RTL_GIGA_MAC_VER_29] = _R("RTL8105e", RTL_TD_1, FIRMWARE_8105E_1), _R("RTL8105e", RTL_TD_1, FIRMWARE_8105E_1, JUMBO_1K, true), [RTL_GIGA_MAC_VER_30] = _R("RTL8105e", RTL_TD_1, FIRMWARE_8105E_1), _R("RTL8105e", RTL_TD_1, FIRMWARE_8105E_1, JUMBO_1K, true), [RTL_GIGA_MAC_VER_31] = _R("RTL8168dp/8111dp", RTL_TD_1, NULL), _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false), [RTL_GIGA_MAC_VER_32] = _R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_1), _R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_1, JUMBO_9K, false), [RTL_GIGA_MAC_VER_33] = _R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_2), _R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_2, JUMBO_9K, false), [RTL_GIGA_MAC_VER_34] = _R("RTL8168evl/8111evl",RTL_TD_1, FIRMWARE_8168E_3) _R("RTL8168evl/8111evl",RTL_TD_1, FIRMWARE_8168E_3, JUMBO_9K, false), [RTL_GIGA_MAC_VER_35] = _R("RTL8168f/8111f", RTL_TD_1, FIRMWARE_8168F_1, JUMBO_9K, false), [RTL_GIGA_MAC_VER_36] = _R("RTL8168f/8111f", RTL_TD_1, FIRMWARE_8168F_2, JUMBO_9K, false), }; #undef _R Loading Loading @@ -311,6 +341,7 @@ enum rtl_registers { MaxTxPacketSize = 0xec, /* 8101/8168. Unit of 128 bytes. */ #define TxPacketMax (8064 >> 7) #define EarlySize 0x27 FuncEvent = 0xf0, FuncEventMask = 0xf4, Loading Loading @@ -460,8 +491,12 @@ enum rtl_register_content { /* Config3 register p.25 */ MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */ LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */ Jumbo_En0 = (1 << 2), /* 8168 only. Reserved in the 8168b */ Beacon_en = (1 << 0), /* 8168 only. Reserved in the 8168b */ /* Config4 register */ Jumbo_En1 = (1 << 1), /* 8168 only. Reserved in the 8168b */ /* Config5 register p.27 */ BWF = (1 << 6), /* Accept Broadcast wakeup frame */ MWF = (1 << 5), /* Accept Multicast wakeup frame */ Loading Loading @@ -670,6 +705,11 @@ struct rtl8169_private { void (*up)(struct rtl8169_private *); } pll_power_ops; struct jumbo_ops { void (*enable)(struct rtl8169_private *); void (*disable)(struct rtl8169_private *); } jumbo_ops; int (*set_speed)(struct net_device *, u8 aneg, u16 sp, u8 dpx, u32 adv); int (*get_settings)(struct net_device *, struct ethtool_cmd *); void (*phy_reset_enable)(struct rtl8169_private *tp); Loading Loading @@ -714,6 +754,8 @@ MODULE_FIRMWARE(FIRMWARE_8168E_1); MODULE_FIRMWARE(FIRMWARE_8168E_2); MODULE_FIRMWARE(FIRMWARE_8168E_3); MODULE_FIRMWARE(FIRMWARE_8105E_1); MODULE_FIRMWARE(FIRMWARE_8168F_1); MODULE_FIRMWARE(FIRMWARE_8168F_2); static int rtl8169_open(struct net_device *dev); static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, Loading @@ -732,6 +774,19 @@ static void rtl8169_down(struct net_device *dev); static void rtl8169_rx_clear(struct rtl8169_private *tp); static int rtl8169_poll(struct napi_struct *napi, int budget); static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force) { int cap = pci_pcie_cap(pdev); if (cap) { u16 ctl; pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl); ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | force; pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl); } } static u32 ocp_read(struct rtl8169_private *tp, u8 mask, u16 reg) { void __iomem *ioaddr = tp->mmio_addr; Loading Loading @@ -1202,6 +1257,19 @@ static void rtl_link_chg_patch(struct rtl8169_private *tp) ERIAR_EXGMAC); rtl_w1w0_eri(ioaddr, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC); } else if (tp->mac_version == RTL_GIGA_MAC_VER_35 || tp->mac_version == RTL_GIGA_MAC_VER_36) { if (RTL_R8(PHYstatus) & _1000bpsF) { rtl_eri_write(ioaddr, 0x1bc, ERIAR_MASK_1111, 0x00000011, ERIAR_EXGMAC); rtl_eri_write(ioaddr, 0x1dc, ERIAR_MASK_1111, 0x00000005, ERIAR_EXGMAC); } else { rtl_eri_write(ioaddr, 0x1bc, ERIAR_MASK_1111, 0x0000001f, ERIAR_EXGMAC); rtl_eri_write(ioaddr, 0x1dc, ERIAR_MASK_1111, 0x0000003f, ERIAR_EXGMAC); } } } Loading Loading @@ -1487,9 +1555,15 @@ static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) static u32 rtl8169_fix_features(struct net_device *dev, u32 features) { struct rtl8169_private *tp = netdev_priv(dev); if (dev->mtu > TD_MSS_MAX) features &= ~NETIF_F_ALL_TSO; if (dev->mtu > JUMBO_1K && !rtl_chip_infos[tp->mac_version].jumbo_tx_csum) features &= ~NETIF_F_IP_CSUM; return features; } Loading Loading @@ -1741,6 +1815,10 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp, u32 val; int mac_version; } mac_info[] = { /* 8168F family. */ { 0x7cf00000, 0x48100000, RTL_GIGA_MAC_VER_36 }, { 0x7cf00000, 0x48000000, RTL_GIGA_MAC_VER_35 }, /* 8168E family. */ { 0x7c800000, 0x2c800000, RTL_GIGA_MAC_VER_34 }, { 0x7cf00000, 0x2c200000, RTL_GIGA_MAC_VER_33 }, Loading Loading @@ -2875,6 +2953,97 @@ static void rtl8168e_2_hw_phy_config(struct rtl8169_private *tp) rtl_writephy(tp, 0x1f, 0x0000); } static void rtl8168f_1_hw_phy_config(struct rtl8169_private *tp) { static const struct phy_reg phy_reg_init[] = { /* Channel estimation fine tune */ { 0x1f, 0x0003 }, { 0x09, 0xa20f }, { 0x1f, 0x0000 }, /* Modify green table for giga & fnet */ { 0x1f, 0x0005 }, { 0x05, 0x8b55 }, { 0x06, 0x0000 }, { 0x05, 0x8b5e }, { 0x06, 0x0000 }, { 0x05, 0x8b67 }, { 0x06, 0x0000 }, { 0x05, 0x8b70 }, { 0x06, 0x0000 }, { 0x1f, 0x0000 }, { 0x1f, 0x0007 }, { 0x1e, 0x0078 }, { 0x17, 0x0000 }, { 0x19, 0x00fb }, { 0x1f, 0x0000 }, /* Modify green table for 10M */ { 0x1f, 0x0005 }, { 0x05, 0x8b79 }, { 0x06, 0xaa00 }, { 0x1f, 0x0000 }, /* Disable hiimpedance detection (RTCT) */ { 0x1f, 0x0003 }, { 0x01, 0x328a }, { 0x1f, 0x0000 } }; rtl_apply_firmware(tp); rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); /* For 4-corner performance improve */ rtl_writephy(tp, 0x1f, 0x0005); rtl_writephy(tp, 0x05, 0x8b80); rtl_w1w0_phy(tp, 0x06, 0x0006, 0x0000); rtl_writephy(tp, 0x1f, 0x0000); /* PHY auto speed down */ rtl_writephy(tp, 0x1f, 0x0007); rtl_writephy(tp, 0x1e, 0x002d); rtl_w1w0_phy(tp, 0x18, 0x0010, 0x0000); rtl_writephy(tp, 0x1f, 0x0000); rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000); /* Improve 10M EEE waveform */ rtl_writephy(tp, 0x1f, 0x0005); rtl_writephy(tp, 0x05, 0x8b86); rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000); rtl_writephy(tp, 0x1f, 0x0000); /* Improve 2-pair detection performance */ rtl_writephy(tp, 0x1f, 0x0005); rtl_writephy(tp, 0x05, 0x8b85); rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000); rtl_writephy(tp, 0x1f, 0x0000); } static void rtl8168f_2_hw_phy_config(struct rtl8169_private *tp) { rtl_apply_firmware(tp); /* For 4-corner performance improve */ rtl_writephy(tp, 0x1f, 0x0005); rtl_writephy(tp, 0x05, 0x8b80); rtl_w1w0_phy(tp, 0x06, 0x0006, 0x0000); rtl_writephy(tp, 0x1f, 0x0000); /* PHY auto speed down */ rtl_writephy(tp, 0x1f, 0x0007); rtl_writephy(tp, 0x1e, 0x002d); rtl_w1w0_phy(tp, 0x18, 0x0010, 0x0000); rtl_writephy(tp, 0x1f, 0x0000); rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000); /* Improve 10M EEE waveform */ rtl_writephy(tp, 0x1f, 0x0005); rtl_writephy(tp, 0x05, 0x8b86); rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000); rtl_writephy(tp, 0x1f, 0x0000); } static void rtl8102e_hw_phy_config(struct rtl8169_private *tp) { static const struct phy_reg phy_reg_init[] = { Loading Loading @@ -2999,6 +3168,12 @@ static void rtl_hw_phy_config(struct net_device *dev) case RTL_GIGA_MAC_VER_34: rtl8168e_2_hw_phy_config(tp); break; case RTL_GIGA_MAC_VER_35: rtl8168f_1_hw_phy_config(tp); break; case RTL_GIGA_MAC_VER_36: rtl8168f_2_hw_phy_config(tp); break; default: break; Loading Loading @@ -3483,7 +3658,7 @@ static void r8168_pll_power_up(struct rtl8169_private *tp) r8168_phy_power_up(tp); } static void rtl_pll_power_op(struct rtl8169_private *tp, static void rtl_generic_op(struct rtl8169_private *tp, void (*op)(struct rtl8169_private *)) { if (op) Loading @@ -3492,12 +3667,12 @@ static void rtl_pll_power_op(struct rtl8169_private *tp, static void rtl_pll_power_down(struct rtl8169_private *tp) { rtl_pll_power_op(tp, tp->pll_power_ops.down); rtl_generic_op(tp, tp->pll_power_ops.down); } static void rtl_pll_power_up(struct rtl8169_private *tp) { rtl_pll_power_op(tp, tp->pll_power_ops.up); rtl_generic_op(tp, tp->pll_power_ops.up); } static void __devinit rtl_init_pll_power_ops(struct rtl8169_private *tp) Loading Loading @@ -3534,6 +3709,8 @@ static void __devinit rtl_init_pll_power_ops(struct rtl8169_private *tp) case RTL_GIGA_MAC_VER_32: case RTL_GIGA_MAC_VER_33: case RTL_GIGA_MAC_VER_34: case RTL_GIGA_MAC_VER_35: case RTL_GIGA_MAC_VER_36: ops->down = r8168_pll_power_down; ops->up = r8168_pll_power_up; break; Loading Loading @@ -3586,6 +3763,150 @@ static void rtl8169_init_ring_indexes(struct rtl8169_private *tp) tp->dirty_tx = tp->dirty_rx = tp->cur_tx = tp->cur_rx = 0; } static void rtl_hw_jumbo_enable(struct rtl8169_private *tp) { rtl_generic_op(tp, tp->jumbo_ops.enable); } static void rtl_hw_jumbo_disable(struct rtl8169_private *tp) { rtl_generic_op(tp, tp->jumbo_ops.disable); } static void r8168c_hw_jumbo_enable(struct rtl8169_private *tp) { void __iomem *ioaddr = tp->mmio_addr; RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0); RTL_W8(Config4, RTL_R8(Config4) | Jumbo_En1); rtl_tx_performance_tweak(tp->pci_dev, 0x2 << MAX_READ_REQUEST_SHIFT); } static void r8168c_hw_jumbo_disable(struct rtl8169_private *tp) { void __iomem *ioaddr = tp->mmio_addr; RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0); RTL_W8(Config4, RTL_R8(Config4) & ~Jumbo_En1); rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT); } static void r8168dp_hw_jumbo_enable(struct rtl8169_private *tp) { void __iomem *ioaddr = tp->mmio_addr; RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0); } static void r8168dp_hw_jumbo_disable(struct rtl8169_private *tp) { void __iomem *ioaddr = tp->mmio_addr; RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0); } static void r8168e_hw_jumbo_enable(struct rtl8169_private *tp) { void __iomem *ioaddr = tp->mmio_addr; struct pci_dev *pdev = tp->pci_dev; RTL_W8(MaxTxPacketSize, 0x3f); RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0); RTL_W8(Config4, RTL_R8(Config4) | 0x01); pci_write_config_byte(pdev, 0x79, 0x20); } static void r8168e_hw_jumbo_disable(struct rtl8169_private *tp) { void __iomem *ioaddr = tp->mmio_addr; struct pci_dev *pdev = tp->pci_dev; RTL_W8(MaxTxPacketSize, 0x0c); RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0); RTL_W8(Config4, RTL_R8(Config4) & ~0x01); pci_write_config_byte(pdev, 0x79, 0x50); } static void r8168b_0_hw_jumbo_enable(struct rtl8169_private *tp) { rtl_tx_performance_tweak(tp->pci_dev, (0x2 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN); } static void r8168b_0_hw_jumbo_disable(struct rtl8169_private *tp) { rtl_tx_performance_tweak(tp->pci_dev, (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN); } static void r8168b_1_hw_jumbo_enable(struct rtl8169_private *tp) { void __iomem *ioaddr = tp->mmio_addr; r8168b_0_hw_jumbo_enable(tp); RTL_W8(Config4, RTL_R8(Config4) | (1 << 0)); } static void r8168b_1_hw_jumbo_disable(struct rtl8169_private *tp) { void __iomem *ioaddr = tp->mmio_addr; r8168b_0_hw_jumbo_disable(tp); RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0)); } static void __devinit rtl_init_jumbo_ops(struct rtl8169_private *tp) { struct jumbo_ops *ops = &tp->jumbo_ops; switch (tp->mac_version) { case RTL_GIGA_MAC_VER_11: ops->disable = r8168b_0_hw_jumbo_disable; ops->enable = r8168b_0_hw_jumbo_enable; break; case RTL_GIGA_MAC_VER_12: case RTL_GIGA_MAC_VER_17: ops->disable = r8168b_1_hw_jumbo_disable; ops->enable = r8168b_1_hw_jumbo_enable; break; case RTL_GIGA_MAC_VER_18: /* Wild guess. Needs info from Realtek. */ case RTL_GIGA_MAC_VER_19: case RTL_GIGA_MAC_VER_20: case RTL_GIGA_MAC_VER_21: /* Wild guess. Needs info from Realtek. */ case RTL_GIGA_MAC_VER_22: case RTL_GIGA_MAC_VER_23: case RTL_GIGA_MAC_VER_24: case RTL_GIGA_MAC_VER_25: case RTL_GIGA_MAC_VER_26: ops->disable = r8168c_hw_jumbo_disable; ops->enable = r8168c_hw_jumbo_enable; break; case RTL_GIGA_MAC_VER_27: case RTL_GIGA_MAC_VER_28: ops->disable = r8168dp_hw_jumbo_disable; ops->enable = r8168dp_hw_jumbo_enable; break; case RTL_GIGA_MAC_VER_31: /* Wild guess. Needs info from Realtek. */ case RTL_GIGA_MAC_VER_32: case RTL_GIGA_MAC_VER_33: case RTL_GIGA_MAC_VER_34: ops->disable = r8168e_hw_jumbo_disable; ops->enable = r8168e_hw_jumbo_enable; break; /* * No action needed for jumbo frames with 8169. * No jumbo for 810x at all. */ default: ops->disable = NULL; ops->enable = NULL; break; } } static void rtl_hw_reset(struct rtl8169_private *tp) { void __iomem *ioaddr = tp->mmio_addr; Loading Loading @@ -3730,6 +4051,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) rtl_init_mdio_ops(tp); rtl_init_pll_power_ops(tp); rtl_init_jumbo_ops(tp); rtl8169_print_mac_version(tp); Loading Loading @@ -3813,6 +4135,12 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) netif_info(tp, probe, dev, "%s at 0x%lx, %pM, XID %08x IRQ %d\n", rtl_chip_infos[chipset].name, dev->base_addr, dev->dev_addr, (u32)(RTL_R32(TxConfig) & 0x9cf0f8ff), dev->irq); if (rtl_chip_infos[chipset].jumbo_max != JUMBO_1K) { netif_info(tp, probe, dev, "jumbo features [frames: %d bytes, " "tx checksumming: %s]\n", rtl_chip_infos[chipset].jumbo_max, rtl_chip_infos[chipset].jumbo_tx_csum ? "ok" : "ko"); } if (tp->mac_version == RTL_GIGA_MAC_VER_27 || tp->mac_version == RTL_GIGA_MAC_VER_28 || Loading Loading @@ -4008,7 +4336,9 @@ static void rtl8169_hw_reset(struct rtl8169_private *tp) tp->mac_version == RTL_GIGA_MAC_VER_31) { while (RTL_R8(TxPoll) & NPQ) udelay(20); } else if (tp->mac_version == RTL_GIGA_MAC_VER_34) { } else if (tp->mac_version == RTL_GIGA_MAC_VER_34 || tp->mac_version == RTL_GIGA_MAC_VER_35 || tp->mac_version == RTL_GIGA_MAC_VER_36) { RTL_W8(ChipCmd, RTL_R8(ChipCmd) | StopReq); while (!(RTL_R32(TxConfig) & TXCFG_EMPTY)) udelay(100); Loading Loading @@ -4167,19 +4497,6 @@ static void rtl_hw_start_8169(struct net_device *dev) RTL_W16(IntrMask, tp->intr_event); } static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force) { int cap = pci_pcie_cap(pdev); if (cap) { u16 ctl; pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &ctl); ctl = (ctl & ~PCI_EXP_DEVCTL_READRQ) | force; pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, ctl); } } static void rtl_csi_access_enable(void __iomem *ioaddr, u32 bits) { u32 csi; Loading Loading @@ -4479,7 +4796,50 @@ static void rtl_hw_start_8168e_2(void __iomem *ioaddr, struct pci_dev *pdev) rtl_w1w0_eri(ioaddr, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0xff00, ERIAR_EXGMAC); RTL_W8(MaxTxPacketSize, 0x27); RTL_W8(MaxTxPacketSize, EarlySize); rtl_disable_clock_request(pdev); RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO); RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB); /* Adjust EEE LED frequency */ RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07); RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN); RTL_W32(MISC, RTL_R32(MISC) | PWM_EN); RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en); } static void rtl_hw_start_8168f_1(void __iomem *ioaddr, struct pci_dev *pdev) { static const struct ephy_info e_info_8168f_1[] = { { 0x06, 0x00c0, 0x0020 }, { 0x08, 0x0001, 0x0002 }, { 0x09, 0x0000, 0x0080 }, { 0x19, 0x0000, 0x0224 } }; rtl_csi_access_enable_1(ioaddr); rtl_ephy_init(ioaddr, e_info_8168f_1, ARRAY_SIZE(e_info_8168f_1)); rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); rtl_eri_write(ioaddr, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); rtl_eri_write(ioaddr, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); rtl_eri_write(ioaddr, 0xc8, ERIAR_MASK_1111, 0x00100002, ERIAR_EXGMAC); rtl_eri_write(ioaddr, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC); rtl_w1w0_eri(ioaddr, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC); rtl_w1w0_eri(ioaddr, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC); rtl_w1w0_eri(ioaddr, 0x1b0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC); rtl_w1w0_eri(ioaddr, 0x1d0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC); rtl_eri_write(ioaddr, 0xcc, ERIAR_MASK_1111, 0x00000050, ERIAR_EXGMAC); rtl_eri_write(ioaddr, 0xd0, ERIAR_MASK_1111, 0x00000060, ERIAR_EXGMAC); rtl_w1w0_eri(ioaddr, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0xff00, ERIAR_EXGMAC); RTL_W8(MaxTxPacketSize, EarlySize); rtl_disable_clock_request(pdev); Loading Loading @@ -4588,6 +4948,11 @@ static void rtl_hw_start_8168(struct net_device *dev) rtl_hw_start_8168e_2(ioaddr, pdev); break; case RTL_GIGA_MAC_VER_35: case RTL_GIGA_MAC_VER_36: rtl_hw_start_8168f_1(ioaddr, pdev); break; default: printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n", dev->name, tp->mac_version); Loading Loading @@ -4759,9 +5124,17 @@ static void rtl_hw_start_8101(struct net_device *dev) static int rtl8169_change_mtu(struct net_device *dev, int new_mtu) { if (new_mtu < ETH_ZLEN || new_mtu > SafeMtu) struct rtl8169_private *tp = netdev_priv(dev); if (new_mtu < ETH_ZLEN || new_mtu > rtl_chip_infos[tp->mac_version].jumbo_max) return -EINVAL; if (new_mtu > ETH_DATA_LEN) rtl_hw_jumbo_enable(tp); else rtl_hw_jumbo_disable(tp); dev->mtu = new_mtu; netdev_update_features(dev); Loading Loading @@ -5356,7 +5729,7 @@ static int rtl8169_rx_interrupt(struct net_device *dev, } else { struct sk_buff *skb; dma_addr_t addr = le64_to_cpu(desc->addr); int pkt_size = (status & 0x00001FFF) - 4; int pkt_size = (status & 0x00003fff) - 4; /* * The driver does not support incoming fragmented Loading