Skip to content

Commit 6bc6c4e

Browse files
hkallweitdavem330
authored andcommitted
r8169: use spinlock to protect access to registers Config2 and Config5
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 <[email protected]> Tested-by: Kai-Heng Feng <[email protected]> Tested-by: Holger Hoffstätte <[email protected]> Signed-off-by: Heiner Kallweit <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 91c8643 commit 6bc6c4e

File tree

1 file changed

+37
-10
lines changed

1 file changed

+37
-10
lines changed

drivers/net/ethernet/realtek/r8169_main.c

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,7 @@ struct rtl8169_private {
613613
struct work_struct work;
614614
} wk;
615615

616+
spinlock_t config25_lock;
616617
spinlock_t mac_ocp_lock;
617618

618619
unsigned supports_gmii:1;
@@ -677,6 +678,28 @@ static void rtl_pci_commit(struct rtl8169_private *tp)
677678
RTL_R8(tp, ChipCmd);
678679
}
679680

681+
static void rtl_mod_config2(struct rtl8169_private *tp, u8 clear, u8 set)
682+
{
683+
unsigned long flags;
684+
u8 val;
685+
686+
spin_lock_irqsave(&tp->config25_lock, flags);
687+
val = RTL_R8(tp, Config2);
688+
RTL_W8(tp, Config2, (val & ~clear) | set);
689+
spin_unlock_irqrestore(&tp->config25_lock, flags);
690+
}
691+
692+
static void rtl_mod_config5(struct rtl8169_private *tp, u8 clear, u8 set)
693+
{
694+
unsigned long flags;
695+
u8 val;
696+
697+
spin_lock_irqsave(&tp->config25_lock, flags);
698+
val = RTL_R8(tp, Config5);
699+
RTL_W8(tp, Config5, (val & ~clear) | set);
700+
spin_unlock_irqrestore(&tp->config25_lock, flags);
701+
}
702+
680703
static bool rtl_is_8125(struct rtl8169_private *tp)
681704
{
682705
return tp->mac_version >= RTL_GIGA_MAC_VER_61;
@@ -1363,6 +1386,7 @@ static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)
13631386
{ WAKE_MAGIC, Config3, MagicPacket }
13641387
};
13651388
unsigned int i, tmp = ARRAY_SIZE(cfg);
1389+
unsigned long flags;
13661390
u8 options;
13671391

13681392
rtl_unlock_config_regs(tp);
@@ -1381,12 +1405,14 @@ static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)
13811405
r8168_mac_ocp_modify(tp, 0xc0b6, BIT(0), 0);
13821406
}
13831407

1408+
spin_lock_irqsave(&tp->config25_lock, flags);
13841409
for (i = 0; i < tmp; i++) {
13851410
options = RTL_R8(tp, cfg[i].reg) & ~cfg[i].mask;
13861411
if (wolopts & cfg[i].opt)
13871412
options |= cfg[i].mask;
13881413
RTL_W8(tp, cfg[i].reg, options);
13891414
}
1415+
spin_unlock_irqrestore(&tp->config25_lock, flags);
13901416

13911417
switch (tp->mac_version) {
13921418
case RTL_GIGA_MAC_VER_02 ... RTL_GIGA_MAC_VER_06:
@@ -1398,10 +1424,10 @@ static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)
13981424
case RTL_GIGA_MAC_VER_34:
13991425
case RTL_GIGA_MAC_VER_37:
14001426
case RTL_GIGA_MAC_VER_39 ... RTL_GIGA_MAC_VER_63:
1401-
options = RTL_R8(tp, Config2) & ~PME_SIGNAL;
14021427
if (wolopts)
1403-
options |= PME_SIGNAL;
1404-
RTL_W8(tp, Config2, options);
1428+
rtl_mod_config2(tp, 0, PME_SIGNAL);
1429+
else
1430+
rtl_mod_config2(tp, PME_SIGNAL, 0);
14051431
break;
14061432
default:
14071433
break;
@@ -2704,8 +2730,8 @@ static void rtl_hw_aspm_clkreq_enable(struct rtl8169_private *tp, bool enable)
27042730
{
27052731
/* Don't enable ASPM in the chip if OS can't control ASPM */
27062732
if (enable && tp->aspm_manageable) {
2707-
RTL_W8(tp, Config5, RTL_R8(tp, Config5) | ASPM_en);
2708-
RTL_W8(tp, Config2, RTL_R8(tp, Config2) | ClkReqEn);
2733+
rtl_mod_config5(tp, 0, ASPM_en);
2734+
rtl_mod_config2(tp, 0, ClkReqEn);
27092735

27102736
switch (tp->mac_version) {
27112737
case RTL_GIGA_MAC_VER_46 ... RTL_GIGA_MAC_VER_48:
@@ -2728,8 +2754,8 @@ static void rtl_hw_aspm_clkreq_enable(struct rtl8169_private *tp, bool enable)
27282754
break;
27292755
}
27302756

2731-
RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~ClkReqEn);
2732-
RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~ASPM_en);
2757+
rtl_mod_config2(tp, ClkReqEn, 0);
2758+
rtl_mod_config5(tp, ASPM_en, 0);
27332759
}
27342760

27352761
udelay(10);
@@ -2890,7 +2916,7 @@ static void rtl_hw_start_8168e_1(struct rtl8169_private *tp)
28902916
RTL_W32(tp, MISC, RTL_R32(tp, MISC) | TXPLA_RST);
28912917
RTL_W32(tp, MISC, RTL_R32(tp, MISC) & ~TXPLA_RST);
28922918

2893-
RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~Spi_en);
2919+
rtl_mod_config5(tp, Spi_en, 0);
28942920
}
28952921

28962922
static void rtl_hw_start_8168e_2(struct rtl8169_private *tp)
@@ -2923,7 +2949,7 @@ static void rtl_hw_start_8168e_2(struct rtl8169_private *tp)
29232949

29242950
RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) | PFM_EN);
29252951
RTL_W32(tp, MISC, RTL_R32(tp, MISC) | PWM_EN);
2926-
RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~Spi_en);
2952+
rtl_mod_config5(tp, Spi_en, 0);
29272953

29282954
rtl_hw_aspm_clkreq_enable(tp, true);
29292955
}
@@ -2946,7 +2972,7 @@ static void rtl_hw_start_8168f(struct rtl8169_private *tp)
29462972
RTL_W8(tp, MCU, RTL_R8(tp, MCU) & ~NOW_IS_OOB);
29472973
RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) | PFM_EN);
29482974
RTL_W32(tp, MISC, RTL_R32(tp, MISC) | PWM_EN);
2949-
RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~Spi_en);
2975+
rtl_mod_config5(tp, Spi_en, 0);
29502976

29512977
rtl8168_config_eee_mac(tp);
29522978
}
@@ -5203,6 +5229,7 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
52035229
tp->eee_adv = -1;
52045230
tp->ocp_base = OCP_STD_PHY_BASE;
52055231

5232+
spin_lock_init(&tp->config25_lock);
52065233
spin_lock_init(&tp->mac_ocp_lock);
52075234

52085235
dev->tstats = devm_netdev_alloc_pcpu_stats(&pdev->dev,

0 commit comments

Comments
 (0)