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 <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>
This commit is contained in:
parent
8ca5a5790b
commit
91c8643578
@ -613,6 +613,8 @@ struct rtl8169_private {
|
||||
struct work_struct work;
|
||||
} wk;
|
||||
|
||||
spinlock_t mac_ocp_lock;
|
||||
|
||||
unsigned supports_gmii:1;
|
||||
unsigned aspm_manageable:1;
|
||||
dma_addr_t counters_phys_addr;
|
||||
@ -847,7 +849,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;
|
||||
@ -855,7 +857,16 @@ static void r8168_mac_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)
|
||||
RTL_W32(tp, OCPDR, OCPAR_FLAG | (reg << 15) | data);
|
||||
}
|
||||
|
||||
static u16 r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg)
|
||||
static void r8168_mac_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&tp->mac_ocp_lock, flags);
|
||||
__r8168_mac_ocp_write(tp, reg, data);
|
||||
spin_unlock_irqrestore(&tp->mac_ocp_lock, flags);
|
||||
}
|
||||
|
||||
static u16 __r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg)
|
||||
{
|
||||
if (rtl_ocp_reg_failure(reg))
|
||||
return 0;
|
||||
@ -865,12 +876,28 @@ 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;
|
||||
|
||||
spin_lock_irqsave(&tp->mac_ocp_lock, flags);
|
||||
val = __r8168_mac_ocp_read(tp, reg);
|
||||
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)
|
||||
{
|
||||
u16 data = r8168_mac_ocp_read(tp, reg);
|
||||
unsigned long flags;
|
||||
u16 data;
|
||||
|
||||
r8168_mac_ocp_write(tp, reg, (data & ~mask) | set);
|
||||
spin_lock_irqsave(&tp->mac_ocp_lock, flags);
|
||||
data = __r8168_mac_ocp_read(tp, reg);
|
||||
__r8168_mac_ocp_write(tp, reg, (data & ~mask) | set);
|
||||
spin_unlock_irqrestore(&tp->mac_ocp_lock, flags);
|
||||
}
|
||||
|
||||
/* 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)
|
||||
tp->eee_adv = -1;
|
||||
tp->ocp_base = OCP_STD_PHY_BASE;
|
||||
|
||||
spin_lock_init(&tp->mac_ocp_lock);
|
||||
|
||||
dev->tstats = devm_netdev_alloc_pcpu_stats(&pdev->dev,
|
||||
struct pcpu_sw_netstats);
|
||||
if (!dev->tstats)
|
||||
|
Loading…
x
Reference in New Issue
Block a user