mirror of
https://github.com/AuxXxilium/r8169.git
synced 2024-11-23 15:00:58 +07:00
fix code for 6.1
This commit is contained in:
parent
4a94bbc954
commit
6699b34dd6
283
r8169_main.c
283
r8169_main.c
@ -30,7 +30,6 @@
|
||||
#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"
|
||||
@ -69,8 +68,6 @@
|
||||
#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
|
||||
|
||||
@ -583,7 +580,6 @@ 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
|
||||
};
|
||||
|
||||
@ -620,12 +616,6 @@ 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;
|
||||
@ -674,22 +664,12 @@ static inline struct device *tp_to_dev(struct rtl8169_private *tp)
|
||||
|
||||
static void rtl_lock_config_regs(struct rtl8169_private *tp)
|
||||
{
|
||||
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);
|
||||
RTL_W8(tp, Cfg9346, Cfg9346_Lock);
|
||||
}
|
||||
|
||||
static void rtl_unlock_config_regs(struct rtl8169_private *tp)
|
||||
{
|
||||
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);
|
||||
RTL_W8(tp, Cfg9346, Cfg9346_Unlock);
|
||||
}
|
||||
|
||||
static void rtl_pci_commit(struct rtl8169_private *tp)
|
||||
@ -698,28 +678,6 @@ 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;
|
||||
@ -892,7 +850,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;
|
||||
@ -900,16 +858,7 @@ static void __r8168_mac_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)
|
||||
RTL_W32(tp, OCPDR, OCPAR_FLAG | (reg << 15) | data);
|
||||
}
|
||||
|
||||
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)
|
||||
static u16 r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg)
|
||||
{
|
||||
if (rtl_ocp_reg_failure(reg))
|
||||
return 0;
|
||||
@ -919,28 +868,12 @@ 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)
|
||||
{
|
||||
unsigned long flags;
|
||||
u16 data;
|
||||
u16 data = r8168_mac_ocp_read(tp, reg);
|
||||
|
||||
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);
|
||||
r8168_mac_ocp_write(tp, reg, (data & ~mask) | set);
|
||||
}
|
||||
|
||||
/* Work around a hw issue with RTL8168g PHY, the quirk disables
|
||||
@ -1406,7 +1339,6 @@ 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);
|
||||
@ -1425,14 +1357,12 @@ 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:
|
||||
@ -1444,10 +1374,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)
|
||||
rtl_mod_config2(tp, 0, PME_SIGNAL);
|
||||
else
|
||||
rtl_mod_config2(tp, PME_SIGNAL, 0);
|
||||
options |= PME_SIGNAL;
|
||||
RTL_W8(tp, Config2, options);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -2748,20 +2678,10 @@ 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) {
|
||||
/* 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);
|
||||
RTL_W8(tp, Config5, RTL_R8(tp, Config5) | ASPM_en);
|
||||
RTL_W8(tp, Config2, RTL_R8(tp, Config2) | ClkReqEn);
|
||||
|
||||
switch (tp->mac_version) {
|
||||
case RTL_GIGA_MAC_VER_46 ... RTL_GIGA_MAC_VER_48:
|
||||
@ -2784,9 +2704,11 @@ static void rtl_hw_aspm_clkreq_enable(struct rtl8169_private *tp, bool enable)
|
||||
break;
|
||||
}
|
||||
|
||||
rtl_mod_config2(tp, ClkReqEn, 0);
|
||||
rtl_mod_config5(tp, ASPM_en, 0);
|
||||
RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~ClkReqEn);
|
||||
RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~ASPM_en);
|
||||
}
|
||||
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
static void rtl_set_fifo_size(struct rtl8169_private *tp, u16 rx_stat,
|
||||
@ -2944,7 +2866,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_mod_config5(tp, Spi_en, 0);
|
||||
RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~Spi_en);
|
||||
}
|
||||
|
||||
static void rtl_hw_start_8168e_2(struct rtl8169_private *tp)
|
||||
@ -2977,7 +2899,9 @@ 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_mod_config5(tp, Spi_en, 0);
|
||||
RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~Spi_en);
|
||||
|
||||
rtl_hw_aspm_clkreq_enable(tp, true);
|
||||
}
|
||||
|
||||
static void rtl_hw_start_8168f(struct rtl8169_private *tp)
|
||||
@ -2998,7 +2922,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_mod_config5(tp, Spi_en, 0);
|
||||
RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~Spi_en);
|
||||
|
||||
rtl8168_config_eee_mac(tp);
|
||||
}
|
||||
@ -3068,7 +2992,11 @@ 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)
|
||||
@ -3086,6 +3014,9 @@ 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);
|
||||
}
|
||||
|
||||
@ -3106,6 +3037,8 @@ 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
|
||||
@ -3243,6 +3176,8 @@ 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)
|
||||
@ -3257,6 +3192,8 @@ 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);
|
||||
@ -3304,6 +3241,8 @@ 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)
|
||||
@ -3342,6 +3281,8 @@ 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);
|
||||
@ -3352,6 +3293,8 @@ 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)
|
||||
@ -3363,6 +3306,9 @@ 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);
|
||||
@ -3412,6 +3358,8 @@ 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)
|
||||
@ -3534,6 +3482,8 @@ 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);
|
||||
|
||||
@ -3550,6 +3500,7 @@ 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)
|
||||
@ -3637,8 +3588,13 @@ 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)
|
||||
@ -3653,8 +3609,12 @@ 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)
|
||||
@ -3750,8 +3710,7 @@ 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)
|
||||
@ -3762,7 +3721,6 @@ 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);
|
||||
@ -3974,7 +3932,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_TX_TIMEOUT);
|
||||
rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
|
||||
}
|
||||
|
||||
static int rtl8169_tx_map(struct rtl8169_private *tp, const u32 *opts, u32 len,
|
||||
@ -4178,9 +4136,13 @@ static bool rtl8169_tso_csum_v2(struct rtl8169_private *tp,
|
||||
return true;
|
||||
}
|
||||
|
||||
static unsigned int rtl_tx_slots_avail(struct rtl8169_private *tp)
|
||||
static bool rtl_tx_slots_avail(struct rtl8169_private *tp)
|
||||
{
|
||||
return READ_ONCE(tp->dirty_tx) + NUM_TX_DESC - READ_ONCE(tp->cur_tx);
|
||||
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;
|
||||
}
|
||||
|
||||
/* Versions RTL8102e and from RTL8168c onwards support csum_v2 */
|
||||
@ -4257,10 +4219,27 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
|
||||
|
||||
WRITE_ONCE(tp->cur_tx, tp->cur_tx + frags + 1);
|
||||
|
||||
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)
|
||||
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)
|
||||
rtl8169_doorbell(tp);
|
||||
|
||||
return NETDEV_TX_OK;
|
||||
@ -4384,12 +4363,19 @@ 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);
|
||||
|
||||
netif_subqueue_completed_wake(dev, 0, pkts_compl, bytes_compl,
|
||||
rtl_tx_slots_avail(tp),
|
||||
R8169_TX_START_THRS);
|
||||
/* 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);
|
||||
/*
|
||||
* 8168 hack: TxPoll requests are lost when the Tx packets are
|
||||
* too close. Let's kick an extra TxPoll request when a burst
|
||||
@ -4540,7 +4526,6 @@ static void rtl_task(struct work_struct *work)
|
||||
{
|
||||
struct rtl8169_private *tp =
|
||||
container_of(work, struct rtl8169_private, wk.work);
|
||||
int ret;
|
||||
|
||||
rtnl_lock();
|
||||
|
||||
@ -4548,27 +4533,7 @@ 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);
|
||||
}
|
||||
@ -4595,13 +4560,12 @@ 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(d);
|
||||
pm_request_resume(&tp->pci_dev->dev);
|
||||
} else {
|
||||
pm_runtime_idle(d);
|
||||
pm_runtime_idle(&tp->pci_dev->dev);
|
||||
}
|
||||
|
||||
phy_print_status(tp->phydev);
|
||||
@ -5055,7 +5019,7 @@ static int r8169_mdio_register(struct rtl8169_private *tp)
|
||||
return -EUNATCH;
|
||||
}
|
||||
|
||||
tp->phydev->mac_managed_pm = true;
|
||||
tp->phydev->mac_managed_pm = 1;
|
||||
|
||||
phy_support_asym_pause(tp->phydev);
|
||||
|
||||
@ -5178,7 +5142,6 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
int jumbo_max, region, rc;
|
||||
enum mac_version chipset;
|
||||
struct net_device *dev;
|
||||
u32 txconfig;
|
||||
u16 xid;
|
||||
|
||||
dev = devm_alloc_etherdev(&pdev->dev, sizeof (*tp));
|
||||
@ -5194,10 +5157,6 @@ 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)
|
||||
@ -5210,35 +5169,38 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
|
||||
/* enable device (incl. PCI PM wakeup and hotplug setup) */
|
||||
rc = pcim_enable_device(pdev);
|
||||
if (rc < 0)
|
||||
return dev_err_probe(&pdev->dev, rc, "enable failure\n");
|
||||
if (rc < 0) {
|
||||
dev_err(&pdev->dev, "enable failure\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (pcim_set_mwi(pdev) < 0)
|
||||
dev_info(&pdev->dev, "Mem-Wr-Inval unavailable\n");
|
||||
|
||||
/* use first MMIO region */
|
||||
region = ffs(pci_select_bars(pdev, IORESOURCE_MEM)) - 1;
|
||||
if (region < 0)
|
||||
return dev_err_probe(&pdev->dev, -ENODEV, "no MMIO resource found\n");
|
||||
if (region < 0) {
|
||||
dev_err(&pdev->dev, "no MMIO resource found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
rc = pcim_iomap_regions(pdev, BIT(region), KBUILD_MODNAME);
|
||||
if (rc < 0)
|
||||
return dev_err_probe(&pdev->dev, rc, "cannot remap MMIO, aborting\n");
|
||||
if (rc < 0) {
|
||||
dev_err(&pdev->dev, "cannot remap MMIO, aborting\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
tp->mmio_addr = pcim_iomap_table(pdev)[region];
|
||||
|
||||
txconfig = RTL_R32(tp, TxConfig);
|
||||
if (txconfig == ~0U)
|
||||
return dev_err_probe(&pdev->dev, -EIO, "PCI read failed\n");
|
||||
|
||||
xid = (txconfig >> 20) & 0xfcf;
|
||||
xid = (RTL_R32(tp, TxConfig) >> 20) & 0xfcf;
|
||||
|
||||
/* Identify chip attached to board */
|
||||
chipset = rtl8169_get_mac_version(xid, tp->supports_gmii);
|
||||
if (chipset == RTL_GIGA_MAC_NONE)
|
||||
return dev_err_probe(&pdev->dev, -ENODEV,
|
||||
"unknown chip XID %03x, contact r8169 maintainers (see MAINTAINERS file)\n",
|
||||
xid);
|
||||
if (chipset == RTL_GIGA_MAC_NONE) {
|
||||
dev_err(&pdev->dev, "unknown chip XID %03x, contact r8169 maintainers (see MAINTAINERS file)\n", xid);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
tp->mac_version = chipset;
|
||||
|
||||
/* Disable ASPM L1 as that cause random device stop working
|
||||
@ -5271,9 +5233,10 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
rtl_hw_reset(tp);
|
||||
|
||||
rc = rtl_alloc_irq(tp);
|
||||
if (rc < 0)
|
||||
return dev_err_probe(&pdev->dev, rc, "Can't allocate interrupt\n");
|
||||
|
||||
if (rc < 0) {
|
||||
dev_err(&pdev->dev, "Can't allocate interrupt\n");
|
||||
return rc;
|
||||
}
|
||||
tp->irq = pci_irq_vector(pdev, 0);
|
||||
|
||||
INIT_WORK(&tp->wk.work, rtl_task);
|
||||
@ -5320,8 +5283,6 @@ 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);
|
||||
|
||||
@ -5384,4 +5345,4 @@ static struct pci_driver rtl8169_pci_driver = {
|
||||
.driver.pm = pm_ptr(&rtl8169_pm_ops),
|
||||
};
|
||||
|
||||
module_pci_driver(rtl8169_pci_driver);
|
||||
module_pci_driver(rtl8169_pci_driver);
|
||||
|
Loading…
Reference in New Issue
Block a user