Skip to content

Commit 91c8643

Browse files
hkallweitdavem330
authored andcommitted
r8169: use spinlock to protect mac ocp register access
For disabling ASPM during NAPI poll we'll have to access mac ocp registers in atomic context. This could result in races because a mac ocp read consists of a write to register OCPDR, followed by a read from the same register. Therefore add a spinlock to protect access to mac ocp registers. 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 8ca5a57 commit 91c8643

File tree

1 file changed

+33
-4
lines changed

1 file changed

+33
-4
lines changed

drivers/net/ethernet/realtek/r8169_main.c

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

616+
spinlock_t mac_ocp_lock;
617+
616618
unsigned supports_gmii:1;
617619
unsigned aspm_manageable:1;
618620
dma_addr_t counters_phys_addr;
@@ -847,15 +849,24 @@ static int r8168_phy_ocp_read(struct rtl8169_private *tp, u32 reg)
847849
(RTL_R32(tp, GPHY_OCP) & 0xffff) : -ETIMEDOUT;
848850
}
849851

850-
static void r8168_mac_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)
852+
static void __r8168_mac_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)
851853
{
852854
if (rtl_ocp_reg_failure(reg))
853855
return;
854856

855857
RTL_W32(tp, OCPDR, OCPAR_FLAG | (reg << 15) | data);
856858
}
857859

858-
static u16 r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg)
860+
static void r8168_mac_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)
861+
{
862+
unsigned long flags;
863+
864+
spin_lock_irqsave(&tp->mac_ocp_lock, flags);
865+
__r8168_mac_ocp_write(tp, reg, data);
866+
spin_unlock_irqrestore(&tp->mac_ocp_lock, flags);
867+
}
868+
869+
static u16 __r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg)
859870
{
860871
if (rtl_ocp_reg_failure(reg))
861872
return 0;
@@ -865,12 +876,28 @@ static u16 r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg)
865876
return RTL_R32(tp, OCPDR);
866877
}
867878

879+
static u16 r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg)
880+
{
881+
unsigned long flags;
882+
u16 val;
883+
884+
spin_lock_irqsave(&tp->mac_ocp_lock, flags);
885+
val = __r8168_mac_ocp_read(tp, reg);
886+
spin_unlock_irqrestore(&tp->mac_ocp_lock, flags);
887+
888+
return val;
889+
}
890+
868891
static void r8168_mac_ocp_modify(struct rtl8169_private *tp, u32 reg, u16 mask,
869892
u16 set)
870893
{
871-
u16 data = r8168_mac_ocp_read(tp, reg);
894+
unsigned long flags;
895+
u16 data;
872896

873-
r8168_mac_ocp_write(tp, reg, (data & ~mask) | set);
897+
spin_lock_irqsave(&tp->mac_ocp_lock, flags);
898+
data = __r8168_mac_ocp_read(tp, reg);
899+
__r8168_mac_ocp_write(tp, reg, (data & ~mask) | set);
900+
spin_unlock_irqrestore(&tp->mac_ocp_lock, flags);
874901
}
875902

876903
/* Work around a hw issue with RTL8168g PHY, the quirk disables
@@ -5176,6 +5203,8 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
51765203
tp->eee_adv = -1;
51775204
tp->ocp_base = OCP_STD_PHY_BASE;
51785205

5206+
spin_lock_init(&tp->mac_ocp_lock);
5207+
51795208
dev->tstats = devm_netdev_alloc_pcpu_stats(&pdev->dev,
51805209
struct pcpu_sw_netstats);
51815210
if (!dev->tstats)

0 commit comments

Comments
 (0)