kernel: add support for kernel 5.4
[openwrt/openwrt.git] / target / linux / generic / backport-5.4 / 729-v5.5-net-sfp-eliminate-mdelay-from-PHY-probe.patch
1 From 0fe72afaa31f98ebd71bd6683fc47021105d0157 Mon Sep 17 00:00:00 2001
2 From: Russell King <rmk+kernel@armlinux.org.uk>
3 Date: Fri, 18 Oct 2019 10:21:46 +0100
4 Subject: [PATCH 627/660] net: sfp: eliminate mdelay() from PHY probe
5
6 Rather than using mdelay() to wait before probing the PHY (which holds
7 several locks, including the rtnl lock), add an extra wait state to
8 the state machine to introduce the 50ms delay without holding any
9 locks.
10
11 Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
12 ---
13 drivers/net/phy/sfp.c | 52 +++++++++++++++++++++++++++++++++----------
14 1 file changed, 40 insertions(+), 12 deletions(-)
15
16 --- a/drivers/net/phy/sfp.c
17 +++ b/drivers/net/phy/sfp.c
18 @@ -54,6 +54,7 @@ enum {
19 SFP_DEV_UP,
20
21 SFP_S_DOWN = 0,
22 + SFP_S_WAIT,
23 SFP_S_INIT,
24 SFP_S_WAIT_LOS,
25 SFP_S_LINK_UP,
26 @@ -110,6 +111,7 @@ static const char *event_to_str(unsigned
27
28 static const char * const sm_state_strings[] = {
29 [SFP_S_DOWN] = "down",
30 + [SFP_S_WAIT] = "wait",
31 [SFP_S_INIT] = "init",
32 [SFP_S_WAIT_LOS] = "wait_los",
33 [SFP_S_LINK_UP] = "link_up",
34 @@ -141,6 +143,7 @@ static const enum gpiod_flags gpio_flags
35 GPIOD_ASIS,
36 };
37
38 +#define T_WAIT msecs_to_jiffies(50)
39 #define T_INIT_JIFFIES msecs_to_jiffies(300)
40 #define T_RESET_US 10
41 #define T_FAULT_RECOVER msecs_to_jiffies(1000)
42 @@ -161,9 +164,6 @@ static const enum gpiod_flags gpio_flags
43 */
44 #define SFP_PHY_ADDR 22
45
46 -/* Give this long for the PHY to reset. */
47 -#define T_PHY_RESET_MS 50
48 -
49 struct sff_data {
50 unsigned int gpios;
51 bool (*module_supported)(const struct sfp_eeprom_id *id);
52 @@ -1267,8 +1267,6 @@ static void sfp_sm_probe_phy(struct sfp
53 struct phy_device *phy;
54 int err;
55
56 - msleep(T_PHY_RESET_MS);
57 -
58 phy = mdiobus_scan(sfp->i2c_mii, SFP_PHY_ADDR);
59 if (phy == ERR_PTR(-ENODEV)) {
60 dev_info(sfp->dev, "no PHY detected\n");
61 @@ -1623,6 +1621,8 @@ static void sfp_sm_module(struct sfp *sf
62
63 static void sfp_sm_main(struct sfp *sfp, unsigned int event)
64 {
65 + unsigned long timeout;
66 +
67 /* Some events are global */
68 if (sfp->sm_state != SFP_S_DOWN &&
69 (sfp->sm_mod_state != SFP_MOD_PRESENT ||
70 @@ -1640,17 +1640,45 @@ static void sfp_sm_main(struct sfp *sfp,
71 /* The main state machine */
72 switch (sfp->sm_state) {
73 case SFP_S_DOWN:
74 - if (sfp->sm_mod_state == SFP_MOD_PRESENT &&
75 - sfp->sm_dev_state == SFP_DEV_UP) {
76 - sfp_sm_mod_init(sfp);
77 - sfp_sm_probe_for_phy(sfp);
78 + if (sfp->sm_mod_state != SFP_MOD_PRESENT ||
79 + sfp->sm_dev_state != SFP_DEV_UP)
80 + break;
81 +
82 + sfp_sm_mod_init(sfp);
83 +
84 + /* Initialise the fault clearance retries */
85 + sfp->sm_retries = 5;
86 +
87 + /* We need to check the TX_FAULT state, which is not defined
88 + * while TX_DISABLE is asserted. The earliest we want to do
89 + * anything (such as probe for a PHY) is 50ms.
90 + */
91 + sfp_sm_next(sfp, SFP_S_WAIT, T_WAIT);
92 + break;
93 +
94 + case SFP_S_WAIT:
95 + if (event != SFP_E_TIMEOUT)
96 + break;
97 +
98 + sfp_sm_probe_for_phy(sfp);
99
100 + if (sfp->state & SFP_F_TX_FAULT) {
101 /* Wait t_init before indicating that the link is up,
102 * provided the current state indicates no TX_FAULT. If
103 * TX_FAULT clears before this time, that's fine too.
104 */
105 - sfp_sm_next(sfp, SFP_S_INIT, T_INIT_JIFFIES);
106 - sfp->sm_retries = 5;
107 + timeout = T_INIT_JIFFIES;
108 + if (timeout > T_WAIT)
109 + timeout -= T_WAIT;
110 + else
111 + timeout = 1;
112 +
113 + sfp_sm_next(sfp, SFP_S_INIT, timeout);
114 + } else {
115 + /* TX_FAULT is not asserted, assume the module has
116 + * finished initialising.
117 + */
118 + goto init_done;
119 }
120 break;
121
122 @@ -1658,7 +1686,7 @@ static void sfp_sm_main(struct sfp *sfp,
123 if (event == SFP_E_TIMEOUT && sfp->state & SFP_F_TX_FAULT)
124 sfp_sm_fault(sfp, true);
125 else if (event == SFP_E_TIMEOUT || event == SFP_E_TX_CLEAR)
126 - sfp_sm_link_check_los(sfp);
127 + init_done: sfp_sm_link_check_los(sfp);
128 break;
129
130 case SFP_S_WAIT_LOS: