mirror of
https://github.com/AuxXxilium/r8169.git
synced 2024-11-23 23:10:59 +07:00
src: update
Signed-off-by: AuxXxilium <info@auxxxilium.tech>
This commit is contained in:
parent
cb60bb9d01
commit
670e669178
273
r8169_main.c
273
r8169_main.c
@ -30,6 +30,7 @@
|
||||
#include <linux/ipv6.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <net/ip6_checksum.h>
|
||||
#include <net/netdev_queues.h>
|
||||
|
||||
#include "r8169.h"
|
||||
#include "r8169_firmware.h"
|
||||
@ -68,6 +69,8 @@
|
||||
#define NUM_RX_DESC 256 /* Number of Rx descriptor registers */
|
||||
#define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc))
|
||||
#define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc))
|
||||
#define R8169_TX_STOP_THRS (MAX_SKB_FRAGS + 1)
|
||||
#define R8169_TX_START_THRS (2 * R8169_TX_STOP_THRS)
|
||||
|
||||
#define OCP_STD_PHY_BASE 0xa400
|
||||
|
||||
@ -139,21 +142,46 @@ static const struct {
|
||||
[RTL_GIGA_MAC_VER_63] = {"RTL8125B", FIRMWARE_8125B_2},
|
||||
};
|
||||
|
||||
/*
|
||||
author: Realtek and the Linux r8168 crew <netdev@vger.kernel.org>
|
||||
srcversion: D2B16DB8E92DC6B16FB1E04
|
||||
alias: pci:v00001186d00004300sv00001186sd00004B10bc*sc*i*
|
||||
alias: pci:v000010ECd00002600sv*sd*bc*sc*i*
|
||||
alias: pci:v000010ECd00002502sv*sd*bc*sc*i*
|
||||
alias: pci:v000010ECd00008161sv*sd*bc*sc*i*
|
||||
alias: pci:v000010ECd00008168sv*sd*bc*sc*i*
|
||||
|
||||
author: Realtek and the Linux r8125 crew <netdev@vger.kernel.org>
|
||||
srcversion: 80AA932EEAEA9E2392B4B5E
|
||||
alias: pci:v000010ECd00005000sv*sd*bc*sc*i*
|
||||
alias: pci:v000010ECd00008126sv*sd*bc*sc*i*
|
||||
alias: pci:v000010ECd00003000sv*sd*bc*sc*i*
|
||||
alias: pci:v000010ECd00008162sv*sd*bc*sc*i*
|
||||
alias: pci:v000010ECd00008125sv*sd*bc*sc*i*
|
||||
*/
|
||||
static const struct pci_device_id rtl8169_pci_tbl[] = {
|
||||
#ifdef INCLUDE_R8168
|
||||
{ PCI_VDEVICE(REALTEK, 0x2502) },
|
||||
{ PCI_VDEVICE(REALTEK, 0x2600) },
|
||||
#endif
|
||||
{ PCI_VDEVICE(REALTEK, 0x8129) },
|
||||
{ PCI_VDEVICE(REALTEK, 0x8136), RTL_CFG_NO_GBIT },
|
||||
#ifdef INCLUDE_R8168
|
||||
{ PCI_VDEVICE(REALTEK, 0x8161) },
|
||||
#endif
|
||||
#ifdef INCLUDE_R8125
|
||||
{ PCI_VDEVICE(REALTEK, 0x8162) },
|
||||
#endif
|
||||
{ PCI_VDEVICE(REALTEK, 0x8167) },
|
||||
#ifdef INCLUDE_R8168
|
||||
{ PCI_VDEVICE(REALTEK, 0x8168) },
|
||||
{ PCI_VDEVICE(NCUBE, 0x8168) },
|
||||
#endif
|
||||
{ PCI_VDEVICE(NCUBE, 0x8168) },
|
||||
{ PCI_VDEVICE(REALTEK, 0x8169) },
|
||||
#ifdef INCLUDE_R8168
|
||||
{ PCI_VENDOR_ID_DLINK, 0x4300,
|
||||
PCI_VENDOR_ID_DLINK, 0x4b10, 0, 0 },
|
||||
#endif
|
||||
{ PCI_VDEVICE(DLINK, 0x4300) },
|
||||
{ PCI_VDEVICE(DLINK, 0x4302) },
|
||||
{ PCI_VDEVICE(AT, 0xc107) },
|
||||
@ -162,8 +190,8 @@ static const struct pci_device_id rtl8169_pci_tbl[] = {
|
||||
{ 0x0001, 0x8168, PCI_ANY_ID, 0x2410 },
|
||||
#ifdef INCLUDE_R8125
|
||||
{ PCI_VDEVICE(REALTEK, 0x8125) },
|
||||
#endif
|
||||
{ PCI_VDEVICE(REALTEK, 0x3000) },
|
||||
#endif
|
||||
{}
|
||||
};
|
||||
|
||||
@ -580,6 +608,7 @@ struct rtl8169_tc_offsets {
|
||||
enum rtl_flag {
|
||||
RTL_FLAG_TASK_ENABLED = 0,
|
||||
RTL_FLAG_TASK_RESET_PENDING,
|
||||
RTL_FLAG_TASK_TX_TIMEOUT,
|
||||
RTL_FLAG_MAX
|
||||
};
|
||||
|
||||
@ -616,6 +645,12 @@ struct rtl8169_private {
|
||||
struct work_struct work;
|
||||
} wk;
|
||||
|
||||
raw_spinlock_t config25_lock;
|
||||
raw_spinlock_t mac_ocp_lock;
|
||||
|
||||
raw_spinlock_t cfg9346_usage_lock;
|
||||
int cfg9346_usage_count;
|
||||
|
||||
unsigned supports_gmii:1;
|
||||
unsigned aspm_manageable:1;
|
||||
dma_addr_t counters_phys_addr;
|
||||
@ -664,12 +699,22 @@ static inline struct device *tp_to_dev(struct rtl8169_private *tp)
|
||||
|
||||
static void rtl_lock_config_regs(struct rtl8169_private *tp)
|
||||
{
|
||||
RTL_W8(tp, Cfg9346, Cfg9346_Lock);
|
||||
unsigned long flags;
|
||||
|
||||
raw_spin_lock_irqsave(&tp->cfg9346_usage_lock, flags);
|
||||
if (!--tp->cfg9346_usage_count)
|
||||
RTL_W8(tp, Cfg9346, Cfg9346_Lock);
|
||||
raw_spin_unlock_irqrestore(&tp->cfg9346_usage_lock, flags);
|
||||
}
|
||||
|
||||
static void rtl_unlock_config_regs(struct rtl8169_private *tp)
|
||||
{
|
||||
RTL_W8(tp, Cfg9346, Cfg9346_Unlock);
|
||||
unsigned long flags;
|
||||
|
||||
raw_spin_lock_irqsave(&tp->cfg9346_usage_lock, flags);
|
||||
if (!tp->cfg9346_usage_count++)
|
||||
RTL_W8(tp, Cfg9346, Cfg9346_Unlock);
|
||||
raw_spin_unlock_irqrestore(&tp->cfg9346_usage_lock, flags);
|
||||
}
|
||||
|
||||
static void rtl_pci_commit(struct rtl8169_private *tp)
|
||||
@ -678,6 +723,28 @@ static void rtl_pci_commit(struct rtl8169_private *tp)
|
||||
RTL_R8(tp, ChipCmd);
|
||||
}
|
||||
|
||||
static void rtl_mod_config2(struct rtl8169_private *tp, u8 clear, u8 set)
|
||||
{
|
||||
unsigned long flags;
|
||||
u8 val;
|
||||
|
||||
raw_spin_lock_irqsave(&tp->config25_lock, flags);
|
||||
val = RTL_R8(tp, Config2);
|
||||
RTL_W8(tp, Config2, (val & ~clear) | set);
|
||||
raw_spin_unlock_irqrestore(&tp->config25_lock, flags);
|
||||
}
|
||||
|
||||
static void rtl_mod_config5(struct rtl8169_private *tp, u8 clear, u8 set)
|
||||
{
|
||||
unsigned long flags;
|
||||
u8 val;
|
||||
|
||||
raw_spin_lock_irqsave(&tp->config25_lock, flags);
|
||||
val = RTL_R8(tp, Config5);
|
||||
RTL_W8(tp, Config5, (val & ~clear) | set);
|
||||
raw_spin_unlock_irqrestore(&tp->config25_lock, flags);
|
||||
}
|
||||
|
||||
static bool rtl_is_8125(struct rtl8169_private *tp)
|
||||
{
|
||||
return tp->mac_version >= RTL_GIGA_MAC_VER_61;
|
||||
@ -850,7 +917,7 @@ static int r8168_phy_ocp_read(struct rtl8169_private *tp, u32 reg)
|
||||
(RTL_R32(tp, GPHY_OCP) & 0xffff) : -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static void r8168_mac_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)
|
||||
static void __r8168_mac_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)
|
||||
{
|
||||
if (rtl_ocp_reg_failure(reg))
|
||||
return;
|
||||
@ -858,7 +925,16 @@ static void r8168_mac_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)
|
||||
RTL_W32(tp, OCPDR, OCPAR_FLAG | (reg << 15) | data);
|
||||
}
|
||||
|
||||
static u16 r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg)
|
||||
static void r8168_mac_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
raw_spin_lock_irqsave(&tp->mac_ocp_lock, flags);
|
||||
__r8168_mac_ocp_write(tp, reg, data);
|
||||
raw_spin_unlock_irqrestore(&tp->mac_ocp_lock, flags);
|
||||
}
|
||||
|
||||
static u16 __r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg)
|
||||
{
|
||||
if (rtl_ocp_reg_failure(reg))
|
||||
return 0;
|
||||
@ -868,12 +944,28 @@ static u16 r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg)
|
||||
return RTL_R32(tp, OCPDR);
|
||||
}
|
||||
|
||||
static u16 r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg)
|
||||
{
|
||||
unsigned long flags;
|
||||
u16 val;
|
||||
|
||||
raw_spin_lock_irqsave(&tp->mac_ocp_lock, flags);
|
||||
val = __r8168_mac_ocp_read(tp, reg);
|
||||
raw_spin_unlock_irqrestore(&tp->mac_ocp_lock, flags);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static void r8168_mac_ocp_modify(struct rtl8169_private *tp, u32 reg, u16 mask,
|
||||
u16 set)
|
||||
{
|
||||
u16 data = r8168_mac_ocp_read(tp, reg);
|
||||
unsigned long flags;
|
||||
u16 data;
|
||||
|
||||
r8168_mac_ocp_write(tp, reg, (data & ~mask) | set);
|
||||
raw_spin_lock_irqsave(&tp->mac_ocp_lock, flags);
|
||||
data = __r8168_mac_ocp_read(tp, reg);
|
||||
__r8168_mac_ocp_write(tp, reg, (data & ~mask) | set);
|
||||
raw_spin_unlock_irqrestore(&tp->mac_ocp_lock, flags);
|
||||
}
|
||||
|
||||
/* Work around a hw issue with RTL8168g PHY, the quirk disables
|
||||
@ -1339,6 +1431,7 @@ static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)
|
||||
{ WAKE_MAGIC, Config3, MagicPacket }
|
||||
};
|
||||
unsigned int i, tmp = ARRAY_SIZE(cfg);
|
||||
unsigned long flags;
|
||||
u8 options;
|
||||
|
||||
rtl_unlock_config_regs(tp);
|
||||
@ -1357,12 +1450,14 @@ static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)
|
||||
r8168_mac_ocp_modify(tp, 0xc0b6, BIT(0), 0);
|
||||
}
|
||||
|
||||
raw_spin_lock_irqsave(&tp->config25_lock, flags);
|
||||
for (i = 0; i < tmp; i++) {
|
||||
options = RTL_R8(tp, cfg[i].reg) & ~cfg[i].mask;
|
||||
if (wolopts & cfg[i].opt)
|
||||
options |= cfg[i].mask;
|
||||
RTL_W8(tp, cfg[i].reg, options);
|
||||
}
|
||||
raw_spin_unlock_irqrestore(&tp->config25_lock, flags);
|
||||
|
||||
switch (tp->mac_version) {
|
||||
case RTL_GIGA_MAC_VER_02 ... RTL_GIGA_MAC_VER_06:
|
||||
@ -1374,10 +1469,10 @@ static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)
|
||||
case RTL_GIGA_MAC_VER_34:
|
||||
case RTL_GIGA_MAC_VER_37:
|
||||
case RTL_GIGA_MAC_VER_39 ... RTL_GIGA_MAC_VER_63:
|
||||
options = RTL_R8(tp, Config2) & ~PME_SIGNAL;
|
||||
if (wolopts)
|
||||
options |= PME_SIGNAL;
|
||||
RTL_W8(tp, Config2, options);
|
||||
rtl_mod_config2(tp, 0, PME_SIGNAL);
|
||||
else
|
||||
rtl_mod_config2(tp, PME_SIGNAL, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -2678,10 +2773,20 @@ static void rtl_disable_exit_l1(struct rtl8169_private *tp)
|
||||
|
||||
static void rtl_hw_aspm_clkreq_enable(struct rtl8169_private *tp, bool enable)
|
||||
{
|
||||
if (tp->mac_version < RTL_GIGA_MAC_VER_32)
|
||||
return;
|
||||
|
||||
/* Don't enable ASPM in the chip if OS can't control ASPM */
|
||||
if (enable && tp->aspm_manageable) {
|
||||
RTL_W8(tp, Config5, RTL_R8(tp, Config5) | ASPM_en);
|
||||
RTL_W8(tp, Config2, RTL_R8(tp, Config2) | ClkReqEn);
|
||||
/* On these chip versions ASPM can even harm
|
||||
* bus communication of other PCI devices.
|
||||
*/
|
||||
if (tp->mac_version == RTL_GIGA_MAC_VER_42 ||
|
||||
tp->mac_version == RTL_GIGA_MAC_VER_43)
|
||||
return;
|
||||
|
||||
rtl_mod_config5(tp, 0, ASPM_en);
|
||||
rtl_mod_config2(tp, 0, ClkReqEn);
|
||||
|
||||
switch (tp->mac_version) {
|
||||
case RTL_GIGA_MAC_VER_46 ... RTL_GIGA_MAC_VER_48:
|
||||
@ -2704,11 +2809,9 @@ static void rtl_hw_aspm_clkreq_enable(struct rtl8169_private *tp, bool enable)
|
||||
break;
|
||||
}
|
||||
|
||||
RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~ClkReqEn);
|
||||
RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~ASPM_en);
|
||||
rtl_mod_config2(tp, ClkReqEn, 0);
|
||||
rtl_mod_config5(tp, ASPM_en, 0);
|
||||
}
|
||||
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
static void rtl_set_fifo_size(struct rtl8169_private *tp, u16 rx_stat,
|
||||
@ -2866,7 +2969,7 @@ static void rtl_hw_start_8168e_1(struct rtl8169_private *tp)
|
||||
RTL_W32(tp, MISC, RTL_R32(tp, MISC) | TXPLA_RST);
|
||||
RTL_W32(tp, MISC, RTL_R32(tp, MISC) & ~TXPLA_RST);
|
||||
|
||||
RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~Spi_en);
|
||||
rtl_mod_config5(tp, Spi_en, 0);
|
||||
}
|
||||
|
||||
static void rtl_hw_start_8168e_2(struct rtl8169_private *tp)
|
||||
@ -2899,9 +3002,7 @@ static void rtl_hw_start_8168e_2(struct rtl8169_private *tp)
|
||||
|
||||
RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) | PFM_EN);
|
||||
RTL_W32(tp, MISC, RTL_R32(tp, MISC) | PWM_EN);
|
||||
RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~Spi_en);
|
||||
|
||||
rtl_hw_aspm_clkreq_enable(tp, true);
|
||||
rtl_mod_config5(tp, Spi_en, 0);
|
||||
}
|
||||
|
||||
static void rtl_hw_start_8168f(struct rtl8169_private *tp)
|
||||
@ -2922,7 +3023,7 @@ static void rtl_hw_start_8168f(struct rtl8169_private *tp)
|
||||
RTL_W8(tp, MCU, RTL_R8(tp, MCU) & ~NOW_IS_OOB);
|
||||
RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) | PFM_EN);
|
||||
RTL_W32(tp, MISC, RTL_R32(tp, MISC) | PWM_EN);
|
||||
RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~Spi_en);
|
||||
rtl_mod_config5(tp, Spi_en, 0);
|
||||
|
||||
rtl8168_config_eee_mac(tp);
|
||||
}
|
||||
@ -2992,11 +3093,7 @@ static void rtl_hw_start_8168g_1(struct rtl8169_private *tp)
|
||||
};
|
||||
|
||||
rtl_hw_start_8168g(tp);
|
||||
|
||||
/* disable aspm and clock request before access ephy */
|
||||
rtl_hw_aspm_clkreq_enable(tp, false);
|
||||
rtl_ephy_init(tp, e_info_8168g_1);
|
||||
rtl_hw_aspm_clkreq_enable(tp, true);
|
||||
}
|
||||
|
||||
static void rtl_hw_start_8168g_2(struct rtl8169_private *tp)
|
||||
@ -3014,9 +3111,6 @@ static void rtl_hw_start_8168g_2(struct rtl8169_private *tp)
|
||||
};
|
||||
|
||||
rtl_hw_start_8168g(tp);
|
||||
|
||||
/* disable aspm and clock request before access ephy */
|
||||
rtl_hw_aspm_clkreq_enable(tp, false);
|
||||
rtl_ephy_init(tp, e_info_8168g_2);
|
||||
}
|
||||
|
||||
@ -3037,8 +3131,6 @@ static void rtl_hw_start_8411_2(struct rtl8169_private *tp)
|
||||
|
||||
rtl_hw_start_8168g(tp);
|
||||
|
||||
/* disable aspm and clock request before access ephy */
|
||||
rtl_hw_aspm_clkreq_enable(tp, false);
|
||||
rtl_ephy_init(tp, e_info_8411_2);
|
||||
|
||||
/* The following Realtek-provided magic fixes an issue with the RX unit
|
||||
@ -3176,8 +3268,6 @@ static void rtl_hw_start_8411_2(struct rtl8169_private *tp)
|
||||
r8168_mac_ocp_write(tp, 0xFC32, 0x0C25);
|
||||
r8168_mac_ocp_write(tp, 0xFC34, 0x00A9);
|
||||
r8168_mac_ocp_write(tp, 0xFC36, 0x012D);
|
||||
|
||||
rtl_hw_aspm_clkreq_enable(tp, true);
|
||||
}
|
||||
|
||||
static void rtl_hw_start_8168h_1(struct rtl8169_private *tp)
|
||||
@ -3192,8 +3282,6 @@ static void rtl_hw_start_8168h_1(struct rtl8169_private *tp)
|
||||
};
|
||||
int rg_saw_cnt;
|
||||
|
||||
/* disable aspm and clock request before access ephy */
|
||||
rtl_hw_aspm_clkreq_enable(tp, false);
|
||||
rtl_ephy_init(tp, e_info_8168h_1);
|
||||
|
||||
rtl_set_fifo_size(tp, 0x08, 0x10, 0x02, 0x06);
|
||||
@ -3241,8 +3329,6 @@ static void rtl_hw_start_8168h_1(struct rtl8169_private *tp)
|
||||
r8168_mac_ocp_write(tp, 0xe63e, 0x0000);
|
||||
r8168_mac_ocp_write(tp, 0xc094, 0x0000);
|
||||
r8168_mac_ocp_write(tp, 0xc09e, 0x0000);
|
||||
|
||||
rtl_hw_aspm_clkreq_enable(tp, true);
|
||||
}
|
||||
|
||||
static void rtl_hw_start_8168ep(struct rtl8169_private *tp)
|
||||
@ -3281,8 +3367,6 @@ static void rtl_hw_start_8168ep_3(struct rtl8169_private *tp)
|
||||
{ 0x1e, 0x0000, 0x2000 },
|
||||
};
|
||||
|
||||
/* disable aspm and clock request before access ephy */
|
||||
rtl_hw_aspm_clkreq_enable(tp, false);
|
||||
rtl_ephy_init(tp, e_info_8168ep_3);
|
||||
|
||||
rtl_hw_start_8168ep(tp);
|
||||
@ -3293,8 +3377,6 @@ static void rtl_hw_start_8168ep_3(struct rtl8169_private *tp)
|
||||
r8168_mac_ocp_modify(tp, 0xd3e2, 0x0fff, 0x0271);
|
||||
r8168_mac_ocp_modify(tp, 0xd3e4, 0x00ff, 0x0000);
|
||||
r8168_mac_ocp_modify(tp, 0xe860, 0x0000, 0x0080);
|
||||
|
||||
rtl_hw_aspm_clkreq_enable(tp, true);
|
||||
}
|
||||
|
||||
static void rtl_hw_start_8117(struct rtl8169_private *tp)
|
||||
@ -3306,9 +3388,6 @@ static void rtl_hw_start_8117(struct rtl8169_private *tp)
|
||||
int rg_saw_cnt;
|
||||
|
||||
rtl8168ep_stop_cmac(tp);
|
||||
|
||||
/* disable aspm and clock request before access ephy */
|
||||
rtl_hw_aspm_clkreq_enable(tp, false);
|
||||
rtl_ephy_init(tp, e_info_8117);
|
||||
|
||||
rtl_set_fifo_size(tp, 0x08, 0x10, 0x02, 0x06);
|
||||
@ -3358,8 +3437,6 @@ static void rtl_hw_start_8117(struct rtl8169_private *tp)
|
||||
|
||||
/* firmware is for MAC only */
|
||||
r8169_apply_firmware(tp);
|
||||
|
||||
rtl_hw_aspm_clkreq_enable(tp, true);
|
||||
}
|
||||
|
||||
static void rtl_hw_start_8102e_1(struct rtl8169_private *tp)
|
||||
@ -3482,8 +3559,6 @@ static void rtl_hw_start_8402(struct rtl8169_private *tp)
|
||||
|
||||
static void rtl_hw_start_8106(struct rtl8169_private *tp)
|
||||
{
|
||||
rtl_hw_aspm_clkreq_enable(tp, false);
|
||||
|
||||
/* Force LAN exit from ASPM if Rx/Tx are not idle */
|
||||
RTL_W32(tp, FuncEvent, RTL_R32(tp, FuncEvent) | 0x002800);
|
||||
|
||||
@ -3500,7 +3575,6 @@ static void rtl_hw_start_8106(struct rtl8169_private *tp)
|
||||
rtl_eri_write(tp, 0x1b0, ERIAR_MASK_0011, 0x0000);
|
||||
|
||||
rtl_pcie_state_l2l3_disable(tp);
|
||||
rtl_hw_aspm_clkreq_enable(tp, true);
|
||||
}
|
||||
|
||||
DECLARE_RTL_COND(rtl_mac_ocp_e00e_cond)
|
||||
@ -3588,13 +3662,8 @@ static void rtl_hw_start_8125a_2(struct rtl8169_private *tp)
|
||||
};
|
||||
|
||||
rtl_set_def_aspm_entry_latency(tp);
|
||||
|
||||
/* disable aspm and clock request before access ephy */
|
||||
rtl_hw_aspm_clkreq_enable(tp, false);
|
||||
rtl_ephy_init(tp, e_info_8125a_2);
|
||||
|
||||
rtl_hw_start_8125_common(tp);
|
||||
rtl_hw_aspm_clkreq_enable(tp, true);
|
||||
}
|
||||
|
||||
static void rtl_hw_start_8125b(struct rtl8169_private *tp)
|
||||
@ -3609,12 +3678,8 @@ static void rtl_hw_start_8125b(struct rtl8169_private *tp)
|
||||
};
|
||||
|
||||
rtl_set_def_aspm_entry_latency(tp);
|
||||
rtl_hw_aspm_clkreq_enable(tp, false);
|
||||
|
||||
rtl_ephy_init(tp, e_info_8125b);
|
||||
rtl_hw_start_8125_common(tp);
|
||||
|
||||
rtl_hw_aspm_clkreq_enable(tp, true);
|
||||
}
|
||||
|
||||
static void rtl_hw_config(struct rtl8169_private *tp)
|
||||
@ -3710,7 +3775,8 @@ static void rtl_hw_start_8169(struct rtl8169_private *tp)
|
||||
static void rtl_hw_start(struct rtl8169_private *tp)
|
||||
{
|
||||
rtl_unlock_config_regs(tp);
|
||||
|
||||
/* disable aspm and clock request before ephy access */
|
||||
rtl_hw_aspm_clkreq_enable(tp, false);
|
||||
RTL_W16(tp, CPlusCmd, tp->cp_cmd);
|
||||
|
||||
if (tp->mac_version <= RTL_GIGA_MAC_VER_06)
|
||||
@ -3721,6 +3787,7 @@ static void rtl_hw_start(struct rtl8169_private *tp)
|
||||
rtl_hw_start_8168(tp);
|
||||
|
||||
rtl_enable_exit_l1(tp);
|
||||
rtl_hw_aspm_clkreq_enable(tp, true);
|
||||
rtl_set_rx_max_size(tp);
|
||||
rtl_set_rx_tx_desc_registers(tp);
|
||||
rtl_lock_config_regs(tp);
|
||||
@ -3932,7 +3999,7 @@ static void rtl8169_tx_timeout(struct net_device *dev, unsigned int txqueue)
|
||||
{
|
||||
struct rtl8169_private *tp = netdev_priv(dev);
|
||||
|
||||
rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
|
||||
rtl_schedule_task(tp, RTL_FLAG_TASK_TX_TIMEOUT);
|
||||
}
|
||||
|
||||
static int rtl8169_tx_map(struct rtl8169_private *tp, const u32 *opts, u32 len,
|
||||
@ -4136,13 +4203,9 @@ static bool rtl8169_tso_csum_v2(struct rtl8169_private *tp,
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool rtl_tx_slots_avail(struct rtl8169_private *tp)
|
||||
static unsigned int rtl_tx_slots_avail(struct rtl8169_private *tp)
|
||||
{
|
||||
unsigned int slots_avail = READ_ONCE(tp->dirty_tx) + NUM_TX_DESC
|
||||
- READ_ONCE(tp->cur_tx);
|
||||
|
||||
/* A skbuff with nr_frags needs nr_frags+1 entries in the tx queue */
|
||||
return slots_avail > MAX_SKB_FRAGS;
|
||||
return READ_ONCE(tp->dirty_tx) + NUM_TX_DESC - READ_ONCE(tp->cur_tx);
|
||||
}
|
||||
|
||||
/* Versions RTL8102e and from RTL8168c onwards support csum_v2 */
|
||||
@ -4219,27 +4282,10 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
|
||||
|
||||
WRITE_ONCE(tp->cur_tx, tp->cur_tx + frags + 1);
|
||||
|
||||
stop_queue = !rtl_tx_slots_avail(tp);
|
||||
if (unlikely(stop_queue)) {
|
||||
/* Avoid wrongly optimistic queue wake-up: rtl_tx thread must
|
||||
* not miss a ring update when it notices a stopped queue.
|
||||
*/
|
||||
smp_wmb();
|
||||
netif_stop_queue(dev);
|
||||
/* Sync with rtl_tx:
|
||||
* - publish queue status and cur_tx ring index (write barrier)
|
||||
* - refresh dirty_tx ring index (read barrier).
|
||||
* May the current thread have a pessimistic view of the ring
|
||||
* status and forget to wake up queue, a racing rtl_tx thread
|
||||
* can't.
|
||||
*/
|
||||
smp_mb__after_atomic();
|
||||
if (rtl_tx_slots_avail(tp))
|
||||
netif_start_queue(dev);
|
||||
door_bell = true;
|
||||
}
|
||||
|
||||
if (door_bell)
|
||||
stop_queue = !netif_subqueue_maybe_stop(dev, 0, rtl_tx_slots_avail(tp),
|
||||
R8169_TX_STOP_THRS,
|
||||
R8169_TX_START_THRS);
|
||||
if (door_bell || stop_queue)
|
||||
rtl8169_doorbell(tp);
|
||||
|
||||
return NETDEV_TX_OK;
|
||||
@ -4363,19 +4409,12 @@ static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp,
|
||||
}
|
||||
|
||||
if (tp->dirty_tx != dirty_tx) {
|
||||
netdev_completed_queue(dev, pkts_compl, bytes_compl);
|
||||
dev_sw_netstats_tx_add(dev, pkts_compl, bytes_compl);
|
||||
WRITE_ONCE(tp->dirty_tx, dirty_tx);
|
||||
|
||||
/* Sync with rtl8169_start_xmit:
|
||||
* - publish dirty_tx ring index (write barrier)
|
||||
* - refresh cur_tx ring index and queue status (read barrier)
|
||||
* May the current thread miss the stopped queue condition,
|
||||
* a racing xmit thread can only have a right view of the
|
||||
* ring status.
|
||||
*/
|
||||
smp_store_mb(tp->dirty_tx, dirty_tx);
|
||||
if (netif_queue_stopped(dev) && rtl_tx_slots_avail(tp))
|
||||
netif_wake_queue(dev);
|
||||
netif_subqueue_completed_wake(dev, 0, pkts_compl, bytes_compl,
|
||||
rtl_tx_slots_avail(tp),
|
||||
R8169_TX_START_THRS);
|
||||
/*
|
||||
* 8168 hack: TxPoll requests are lost when the Tx packets are
|
||||
* too close. Let's kick an extra TxPoll request when a burst
|
||||
@ -4526,6 +4565,7 @@ static void rtl_task(struct work_struct *work)
|
||||
{
|
||||
struct rtl8169_private *tp =
|
||||
container_of(work, struct rtl8169_private, wk.work);
|
||||
int ret;
|
||||
|
||||
rtnl_lock();
|
||||
|
||||
@ -4533,7 +4573,27 @@ static void rtl_task(struct work_struct *work)
|
||||
!test_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags))
|
||||
goto out_unlock;
|
||||
|
||||
if (test_and_clear_bit(RTL_FLAG_TASK_TX_TIMEOUT, tp->wk.flags)) {
|
||||
/* if chip isn't accessible, reset bus to revive it */
|
||||
if (RTL_R32(tp, TxConfig) == ~0) {
|
||||
ret = pci_reset_bus(tp->pci_dev);
|
||||
if (ret < 0) {
|
||||
netdev_err(tp->dev, "Can't reset secondary PCI bus, detach NIC\n");
|
||||
netif_device_detach(tp->dev);
|
||||
goto out_unlock;
|
||||
}
|
||||
}
|
||||
|
||||
/* ASPM compatibility issues are a typical reason for tx timeouts */
|
||||
ret = pci_disable_link_state(tp->pci_dev, PCIE_LINK_STATE_L1 |
|
||||
PCIE_LINK_STATE_L0S);
|
||||
if (!ret)
|
||||
netdev_warn_once(tp->dev, "ASPM disabled on Tx timeout\n");
|
||||
goto reset;
|
||||
}
|
||||
|
||||
if (test_and_clear_bit(RTL_FLAG_TASK_RESET_PENDING, tp->wk.flags)) {
|
||||
reset:
|
||||
rtl_reset_work(tp);
|
||||
netif_wake_queue(tp->dev);
|
||||
}
|
||||
@ -4560,12 +4620,13 @@ static int rtl8169_poll(struct napi_struct *napi, int budget)
|
||||
static void r8169_phylink_handler(struct net_device *ndev)
|
||||
{
|
||||
struct rtl8169_private *tp = netdev_priv(ndev);
|
||||
struct device *d = tp_to_dev(tp);
|
||||
|
||||
if (netif_carrier_ok(ndev)) {
|
||||
rtl_link_chg_patch(tp);
|
||||
pm_request_resume(&tp->pci_dev->dev);
|
||||
pm_request_resume(d);
|
||||
} else {
|
||||
pm_runtime_idle(&tp->pci_dev->dev);
|
||||
pm_runtime_idle(d);
|
||||
}
|
||||
|
||||
phy_print_status(tp->phydev);
|
||||
@ -5019,7 +5080,7 @@ static int r8169_mdio_register(struct rtl8169_private *tp)
|
||||
return -EUNATCH;
|
||||
}
|
||||
|
||||
tp->phydev->mac_managed_pm = 1;
|
||||
tp->phydev->mac_managed_pm = true;
|
||||
|
||||
phy_support_asym_pause(tp->phydev);
|
||||
|
||||
@ -5157,6 +5218,10 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
tp->eee_adv = -1;
|
||||
tp->ocp_base = OCP_STD_PHY_BASE;
|
||||
|
||||
raw_spin_lock_init(&tp->cfg9346_usage_lock);
|
||||
raw_spin_lock_init(&tp->config25_lock);
|
||||
raw_spin_lock_init(&tp->mac_ocp_lock);
|
||||
|
||||
dev->tstats = devm_netdev_alloc_pcpu_stats(&pdev->dev,
|
||||
struct pcpu_sw_netstats);
|
||||
if (!dev->tstats)
|
||||
@ -5205,13 +5270,9 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
|
||||
/* Disable ASPM L1 as that cause random device stop working
|
||||
* problems as well as full system hangs for some PCIe devices users.
|
||||
* Chips from RTL8168h partially have issues with L1.2, but seem
|
||||
* to work fine with L1 and L1.1.
|
||||
*/
|
||||
if (rtl_aspm_is_safe(tp))
|
||||
rc = 0;
|
||||
else if (tp->mac_version >= RTL_GIGA_MAC_VER_46)
|
||||
rc = pci_disable_link_state(pdev, PCIE_LINK_STATE_L1_2);
|
||||
else
|
||||
rc = pci_disable_link_state(pdev, PCIE_LINK_STATE_L1);
|
||||
tp->aspm_manageable = !rc;
|
||||
@ -5283,6 +5344,8 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
dev->hw_features |= NETIF_F_RXALL;
|
||||
dev->hw_features |= NETIF_F_RXFCS;
|
||||
|
||||
netdev_sw_irq_coalesce_default_on(dev);
|
||||
|
||||
/* configure chip for default features */
|
||||
rtl8169_set_features(dev, dev->features);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user