Skip to content

Commit

Permalink
r8169: use spinlock to protect mac ocp register access
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
hkallweit authored and davem330 committed Mar 8, 2023
1 parent 8ca5a57 commit 91c8643
Showing 1 changed file with 33 additions and 4 deletions.
37 changes: 33 additions & 4 deletions drivers/net/ethernet/realtek/r8169_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -847,15 +849,24 @@ 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;

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;
Expand All @@ -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
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit 91c8643

Please sign in to comment.