aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/ath79/patches-5.15/930-ar8216-make-reg-access-atomic.patch
blob: 02f763534e43ab2e40e337afe66dd8d10cf1070a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
From b3797d1a92afe97c173b00fdb7824cedba24eef0 Mon Sep 17 00:00:00 2001
From: Chuanhong Guo <gch981213@gmail.com>
Date: Sun, 20 Sep 2020 01:00:45 +0800
Subject: [PATCH] ath79: ar8216: make switch register access atomic

due to some unknown reason these register accesses sometimes fail
on the integrated switch without this patch.

THIS ONLY WORKS ON ATH79 AND MAY BREAK THE DRIVER ON OTHER PLATFORMS!
The mdio bus on ath79 works in polling mode and doesn't rely on
any interrupt. This patch breaks the driver on any mdio master
with interrupts used.

---
--- a/drivers/net/phy/ar8216.c
+++ b/drivers/net/phy/ar8216.c
@@ -252,6 +252,7 @@ ar8xxx_mii_write32(struct ar8xxx_priv *p
 u32
 ar8xxx_read(struct ar8xxx_priv *priv, int reg)
 {
+	unsigned long flags;
 	struct mii_bus *bus = priv->mii_bus;
 	u16 r1, r2, page;
 	u32 val;
@@ -259,11 +260,13 @@ ar8xxx_read(struct ar8xxx_priv *priv, in
 	split_addr((u32) reg, &r1, &r2, &page);
 
 	mutex_lock(&bus->mdio_lock);
+	local_irq_save(flags);
 
 	bus->write(bus, 0x18, 0, page);
 	wait_for_page_switch();
 	val = ar8xxx_mii_read32(priv, 0x10 | r2, r1);
 
+	local_irq_restore(flags);
 	mutex_unlock(&bus->mdio_lock);
 
 	return val;
@@ -272,17 +275,20 @@ ar8xxx_read(struct ar8xxx_priv *priv, in
 void
 ar8xxx_write(struct ar8xxx_priv *priv, int reg, u32 val)
 {
+	unsigned long flags;
 	struct mii_bus *bus = priv->mii_bus;
 	u16 r1, r2, page;
 
 	split_addr((u32) reg, &r1, &r2, &page);
 
 	mutex_lock(&bus->mdio_lock);
+	local_irq_save(flags);
 
 	bus->write(bus, 0x18, 0, page);
 	wait_for_page_switch();
 	ar8xxx_mii_write32(priv, 0x10 | r2, r1, val);
 
+	local_irq_restore(flags);
 	mutex_unlock(&bus->mdio_lock);
 }