26b6a6b0e4a15cfba8b9a7023df60f69cbb7507a
[openwrt/openwrt.git] / target / linux / generic / backport-5.4 / 734-v5.5-net-sfp-move-module-insert-reporting-out-of-probe.patch
1 From 57cbf7453551db1df619b79410d79fc418d862d5 Mon Sep 17 00:00:00 2001
2 From: Russell King <rmk+kernel@armlinux.org.uk>
3 Date: Tue, 5 Nov 2019 13:00:45 +0000
4 Subject: [PATCH 632/660] net: sfp: move module insert reporting out of probe
5
6 Move the module insertion reporting out of the probe handling, but
7 after we have detected that the upstream has attached (since that is
8 whom we are reporting insertion to.)
9
10 Only report module removal if we had previously reported a module
11 insertion.
12
13 This gives cleaner semantics, and means we can probe the module before
14 we have an upstream attached.
15
16 Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
17 ---
18 drivers/net/phy/sfp.c | 58 +++++++++++++++++++++++++++++--------------
19 1 file changed, 40 insertions(+), 18 deletions(-)
20
21 --- a/drivers/net/phy/sfp.c
22 +++ b/drivers/net/phy/sfp.c
23 @@ -45,11 +45,12 @@ enum {
24 SFP_E_TIMEOUT,
25
26 SFP_MOD_EMPTY = 0,
27 + SFP_MOD_ERROR,
28 SFP_MOD_PROBE,
29 + SFP_MOD_WAITDEV,
30 SFP_MOD_HPOWER,
31 SFP_MOD_WAITPWR,
32 SFP_MOD_PRESENT,
33 - SFP_MOD_ERROR,
34
35 SFP_DEV_DETACHED = 0,
36 SFP_DEV_DOWN,
37 @@ -68,11 +69,12 @@ enum {
38
39 static const char * const mod_state_strings[] = {
40 [SFP_MOD_EMPTY] = "empty",
41 + [SFP_MOD_ERROR] = "error",
42 [SFP_MOD_PROBE] = "probe",
43 + [SFP_MOD_WAITDEV] = "waitdev",
44 [SFP_MOD_HPOWER] = "hpower",
45 [SFP_MOD_WAITPWR] = "waitpwr",
46 [SFP_MOD_PRESENT] = "present",
47 - [SFP_MOD_ERROR] = "error",
48 };
49
50 static const char *mod_state_to_str(unsigned short mod_state)
51 @@ -1479,16 +1481,13 @@ static int sfp_sm_mod_probe(struct sfp *
52 if (ret < 0)
53 return ret;
54
55 - ret = sfp_module_insert(sfp->sfp_bus, &sfp->id);
56 - if (ret < 0)
57 - return ret;
58 -
59 return 0;
60 }
61
62 static void sfp_sm_mod_remove(struct sfp *sfp)
63 {
64 - sfp_module_remove(sfp->sfp_bus);
65 + if (sfp->sm_mod_state > SFP_MOD_WAITDEV)
66 + sfp_module_remove(sfp->sfp_bus);
67
68 sfp_hwmon_remove(sfp);
69
70 @@ -1539,12 +1538,12 @@ static void sfp_sm_module(struct sfp *sf
71 }
72
73 /* Handle device detach globally */
74 - if (sfp->sm_dev_state < SFP_DEV_DOWN) {
75 + if (sfp->sm_dev_state < SFP_DEV_DOWN &&
76 + sfp->sm_mod_state > SFP_MOD_WAITDEV) {
77 if (sfp->module_power_mW > 1000 &&
78 sfp->sm_mod_state > SFP_MOD_HPOWER)
79 sfp_sm_mod_hpower(sfp, false);
80 - if (sfp->sm_mod_state > SFP_MOD_EMPTY)
81 - sfp_sm_mod_next(sfp, SFP_MOD_EMPTY, 0);
82 + sfp_sm_mod_next(sfp, SFP_MOD_WAITDEV, 0);
83 return;
84 }
85
86 @@ -1555,6 +1554,7 @@ static void sfp_sm_module(struct sfp *sf
87 break;
88
89 case SFP_MOD_PROBE:
90 + /* Wait for T_PROBE_INIT to time out */
91 if (event != SFP_E_TIMEOUT)
92 break;
93
94 @@ -1568,6 +1568,20 @@ static void sfp_sm_module(struct sfp *sf
95 break;
96 }
97
98 + sfp_sm_mod_next(sfp, SFP_MOD_WAITDEV, 0);
99 + /* fall through */
100 + case SFP_MOD_WAITDEV:
101 + /* Ensure that the device is attached before proceeding */
102 + if (sfp->sm_dev_state < SFP_DEV_DOWN)
103 + break;
104 +
105 + /* Report the module insertion to the upstream device */
106 + err = sfp_module_insert(sfp->sfp_bus, &sfp->id);
107 + if (err < 0) {
108 + sfp_sm_mod_next(sfp, SFP_MOD_ERROR, 0);
109 + break;
110 + }
111 +
112 /* If this is a power level 1 module, we are done */
113 if (sfp->module_power_mW <= 1000)
114 goto insert;
115 @@ -1577,12 +1591,17 @@ static void sfp_sm_module(struct sfp *sf
116 case SFP_MOD_HPOWER:
117 /* Enable high power mode */
118 err = sfp_sm_mod_hpower(sfp, true);
119 - if (err == 0)
120 - sfp_sm_mod_next(sfp, SFP_MOD_WAITPWR, T_HPOWER_LEVEL);
121 - else if (err != -EAGAIN)
122 - sfp_sm_mod_next(sfp, SFP_MOD_ERROR, 0);
123 - else
124 - sfp_sm_set_timer(sfp, T_PROBE_RETRY);
125 + if (err < 0) {
126 + if (err != -EAGAIN) {
127 + sfp_module_remove(sfp->sfp_bus);
128 + sfp_sm_mod_next(sfp, SFP_MOD_ERROR, 0);
129 + } else {
130 + sfp_sm_set_timer(sfp, T_PROBE_RETRY);
131 + }
132 + break;
133 + }
134 +
135 + sfp_sm_mod_next(sfp, SFP_MOD_WAITPWR, T_HPOWER_LEVEL);
136 break;
137
138 case SFP_MOD_WAITPWR:
139 @@ -1750,8 +1769,6 @@ static void sfp_sm_event(struct sfp *sfp
140 static void sfp_attach(struct sfp *sfp)
141 {
142 sfp_sm_event(sfp, SFP_E_DEV_ATTACH);
143 - if (sfp->state & SFP_F_PRESENT)
144 - sfp_sm_event(sfp, SFP_E_INSERT);
145 }
146
147 static void sfp_detach(struct sfp *sfp)
148 @@ -2001,6 +2018,11 @@ static int sfp_probe(struct platform_dev
149 sfp->state |= SFP_F_RATE_SELECT;
150 sfp_set_state(sfp, sfp->state);
151 sfp_module_tx_disable(sfp);
152 + if (sfp->state & SFP_F_PRESENT) {
153 + rtnl_lock();
154 + sfp_sm_event(sfp, SFP_E_INSERT);
155 + rtnl_unlock();
156 + }
157
158 for (i = 0; i < GPIO_MAX; i++) {
159 if (gpio_flags[i] != GPIOD_IN || !sfp->gpio[i])