Skip to content

Commit

Permalink
r8169: use spinlock to protect access to registers Config2 and Config5
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Heiner Kallweit authored and David S. Miller committed Mar 8, 2023
1 parent 91c8643 commit 6bc6c4e
Showing 1 changed file with 37 additions and 10 deletions.
47 changes: 37 additions & 10 deletions drivers/net/ethernet/realtek/r8169_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,7 @@ struct rtl8169_private {
struct work_struct work;
} wk;

spinlock_t config25_lock;
spinlock_t mac_ocp_lock;

unsigned supports_gmii:1;
Expand Down Expand Up @@ -677,6 +678,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;
Expand Down Expand Up @@ -1363,6 +1386,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);
Expand All @@ -1381,12 +1405,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:
Expand All @@ -1398,10 +1424,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;
Expand Down Expand Up @@ -2704,8 +2730,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:
Expand All @@ -2728,8 +2754,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);
Expand Down Expand Up @@ -2890,7 +2916,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)
Expand Down Expand Up @@ -2923,7 +2949,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);
}
Expand All @@ -2946,7 +2972,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);
}
Expand Down Expand Up @@ -5203,6 +5229,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,
Expand Down

0 comments on commit 6bc6c4e

Please sign in to comment.