mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 02:21:52 +09:00
r8169: use spinlock to protect access to registers Config2 and Config5
[ Upstream commit 6bc6c4e689 ]
For disabling ASPM during NAPI poll we'll have to access both registers
in atomic context. Use a spinlock to protect access.
Reviewed-by: Simon Horman <simon.horman@corigine.com>
Tested-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
Tested-by: Holger Hoffstätte <holger@applied-asynchrony.com>
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Stable-dep-of: 5e864d90b208 ("r8169: skip DASH fw status checks when DASH is disabled")
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
a33b7cb184
commit
9109472e71
@@ -615,6 +615,7 @@ struct rtl8169_private {
|
||||
struct work_struct work;
|
||||
} wk;
|
||||
|
||||
spinlock_t config25_lock;
|
||||
spinlock_t mac_ocp_lock;
|
||||
|
||||
unsigned supports_gmii:1;
|
||||
@@ -680,6 +681,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;
|
||||
|
||||
spin_lock_irqsave(&tp->config25_lock, flags);
|
||||
val = RTL_R8(tp, Config2);
|
||||
RTL_W8(tp, Config2, (val & ~clear) | set);
|
||||
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;
|
||||
|
||||
spin_lock_irqsave(&tp->config25_lock, flags);
|
||||
val = RTL_R8(tp, Config5);
|
||||
RTL_W8(tp, Config5, (val & ~clear) | set);
|
||||
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;
|
||||
@@ -1401,6 +1424,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);
|
||||
@@ -1419,12 +1443,14 @@ static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)
|
||||
r8168_mac_ocp_modify(tp, 0xc0b6, BIT(0), 0);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
spin_unlock_irqrestore(&tp->config25_lock, flags);
|
||||
|
||||
switch (tp->mac_version) {
|
||||
case RTL_GIGA_MAC_VER_02 ... RTL_GIGA_MAC_VER_06:
|
||||
@@ -1436,10 +1462,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;
|
||||
@@ -2748,8 +2774,8 @@ static void rtl_hw_aspm_clkreq_enable(struct rtl8169_private *tp, bool enable)
|
||||
{
|
||||
/* 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);
|
||||
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:
|
||||
@@ -2772,8 +2798,8 @@ 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);
|
||||
@@ -2934,7 +2960,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)
|
||||
@@ -2967,7 +2993,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_mod_config5(tp, Spi_en, 0);
|
||||
|
||||
rtl_hw_aspm_clkreq_enable(tp, true);
|
||||
}
|
||||
@@ -2990,7 +3016,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);
|
||||
}
|
||||
@@ -5259,6 +5285,7 @@ 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;
|
||||
|
||||
spin_lock_init(&tp->config25_lock);
|
||||
spin_lock_init(&tp->mac_ocp_lock);
|
||||
|
||||
dev->tstats = devm_netdev_alloc_pcpu_stats(&pdev->dev,
|
||||
|
||||
Reference in New Issue
Block a user