generic: mt7530: fix null pointer dereferencing in port5 setup
[oweals/openwrt.git] / target / linux / generic / backport-5.4 / 736-v5.5-net-sfp-allow-modules-with-slow-diagnostics-to-probe.patch
1 From 559391fc20fae506adcb311b904cc544c76436c0 Mon Sep 17 00:00:00 2001
2 From: Russell King <rmk+kernel@armlinux.org.uk>
3 Date: Thu, 7 Nov 2019 18:52:07 +0000
4 Subject: [PATCH 634/660] net: sfp: allow modules with slow diagnostics to
5  probe
6
7 When a module is inserted, we attempt to read read the ID from address
8 0x50.  Once we are able to read the ID, we immediately attempt to
9 initialise the hwmon support by reading from address 0x51.  If this
10 fails, then we fall into error state, and assume that the module is
11 not usable.
12
13 Modules such as the ALCATELLUCENT 3FE46541AA use a real EEPROM for
14 I2C address 0x50, which responds immediately.  However, address 0x51
15 is an emulated, which only becomes available once the on-board firmware
16 has booted.  This prompts us to fall into the error state.
17
18 Since the module may be usable without diagnostics, arrange for the
19 hwmon probe independent of the rest of the SFP itself, retrying every
20 5s for up to about 60s for the monitoring to become available, and
21 print an error message if it doesn't become available.
22
23 Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
24 ---
25  drivers/net/phy/sfp.c | 96 +++++++++++++++++++++++++++++++++----------
26  1 file changed, 74 insertions(+), 22 deletions(-)
27
28 --- a/drivers/net/phy/sfp.c
29 +++ b/drivers/net/phy/sfp.c
30 @@ -218,6 +218,8 @@ struct sfp {
31  
32  #if IS_ENABLED(CONFIG_HWMON)
33         struct sfp_diag diag;
34 +       struct delayed_work hwmon_probe;
35 +       unsigned int hwmon_tries;
36         struct device *hwmon_dev;
37         char *hwmon_name;
38  #endif
39 @@ -1159,29 +1161,27 @@ static const struct hwmon_chip_info sfp_
40         .info = sfp_hwmon_info,
41  };
42  
43 -static int sfp_hwmon_insert(struct sfp *sfp)
44 +static void sfp_hwmon_probe(struct work_struct *work)
45  {
46 +       struct sfp *sfp = container_of(work, struct sfp, hwmon_probe.work);
47         int err, i;
48  
49 -       if (sfp->id.ext.sff8472_compliance == SFP_SFF8472_COMPLIANCE_NONE)
50 -               return 0;
51 -
52 -       if (!(sfp->id.ext.diagmon & SFP_DIAGMON_DDM))
53 -               return 0;
54 -
55 -       if (sfp->id.ext.diagmon & SFP_DIAGMON_ADDRMODE)
56 -               /* This driver in general does not support address
57 -                * change.
58 -                */
59 -               return 0;
60 -
61         err = sfp_read(sfp, true, 0, &sfp->diag, sizeof(sfp->diag));
62 -       if (err < 0)
63 -               return err;
64 +       if (err < 0) {
65 +               if (sfp->hwmon_tries--) {
66 +                       mod_delayed_work(system_wq, &sfp->hwmon_probe,
67 +                                        T_PROBE_RETRY_SLOW);
68 +               } else {
69 +                       dev_warn(sfp->dev, "hwmon probe failed: %d\n", err);
70 +               }
71 +               return;
72 +       }
73  
74         sfp->hwmon_name = kstrdup(dev_name(sfp->dev), GFP_KERNEL);
75 -       if (!sfp->hwmon_name)
76 -               return -ENODEV;
77 +       if (!sfp->hwmon_name) {
78 +               dev_err(sfp->dev, "out of memory for hwmon name\n");
79 +               return;
80 +       }
81  
82         for (i = 0; sfp->hwmon_name[i]; i++)
83                 if (hwmon_is_bad_char(sfp->hwmon_name[i]))
84 @@ -1191,18 +1191,52 @@ static int sfp_hwmon_insert(struct sfp *
85                                                          sfp->hwmon_name, sfp,
86                                                          &sfp_hwmon_chip_info,
87                                                          NULL);
88 +       if (IS_ERR(sfp->hwmon_dev))
89 +               dev_err(sfp->dev, "failed to register hwmon device: %ld\n",
90 +                       PTR_ERR(sfp->hwmon_dev));
91 +}
92 +
93 +static int sfp_hwmon_insert(struct sfp *sfp)
94 +{
95 +       if (sfp->id.ext.sff8472_compliance == SFP_SFF8472_COMPLIANCE_NONE)
96 +               return 0;
97 +
98 +       if (!(sfp->id.ext.diagmon & SFP_DIAGMON_DDM))
99 +               return 0;
100 +
101 +       if (sfp->id.ext.diagmon & SFP_DIAGMON_ADDRMODE)
102 +               /* This driver in general does not support address
103 +                * change.
104 +                */
105 +               return 0;
106 +
107 +       mod_delayed_work(system_wq, &sfp->hwmon_probe, 1);
108 +       sfp->hwmon_tries = R_PROBE_RETRY_SLOW;
109  
110 -       return PTR_ERR_OR_ZERO(sfp->hwmon_dev);
111 +       return 0;
112  }
113  
114  static void sfp_hwmon_remove(struct sfp *sfp)
115  {
116 +       cancel_delayed_work_sync(&sfp->hwmon_probe);
117         if (!IS_ERR_OR_NULL(sfp->hwmon_dev)) {
118                 hwmon_device_unregister(sfp->hwmon_dev);
119                 sfp->hwmon_dev = NULL;
120                 kfree(sfp->hwmon_name);
121         }
122  }
123 +
124 +static int sfp_hwmon_init(struct sfp *sfp)
125 +{
126 +       INIT_DELAYED_WORK(&sfp->hwmon_probe, sfp_hwmon_probe);
127 +
128 +       return 0;
129 +}
130 +
131 +static void sfp_hwmon_exit(struct sfp *sfp)
132 +{
133 +       cancel_delayed_work_sync(&sfp->hwmon_probe);
134 +}
135  #else
136  static int sfp_hwmon_insert(struct sfp *sfp)
137  {
138 @@ -1212,6 +1246,15 @@ static int sfp_hwmon_insert(struct sfp *
139  static void sfp_hwmon_remove(struct sfp *sfp)
140  {
141  }
142 +
143 +static int sfp_hwmon_init(struct sfp *sfp)
144 +{
145 +       return 0;
146 +}
147 +
148 +static void sfp_hwmon_exit(struct sfp *sfp)
149 +{
150 +}
151  #endif
152  
153  /* Helpers */
154 @@ -1548,10 +1591,6 @@ static int sfp_sm_mod_probe(struct sfp *
155         if (ret < 0)
156                 return ret;
157  
158 -       ret = sfp_hwmon_insert(sfp);
159 -       if (ret < 0)
160 -               return ret;
161 -
162         return 0;
163  }
164  
165 @@ -1700,6 +1739,15 @@ static void sfp_sm_module(struct sfp *sf
166         case SFP_MOD_ERROR:
167                 break;
168         }
169 +
170 +#if IS_ENABLED(CONFIG_HWMON)
171 +       if (sfp->sm_mod_state >= SFP_MOD_WAITDEV &&
172 +           IS_ERR_OR_NULL(sfp->hwmon_dev)) {
173 +               err = sfp_hwmon_insert(sfp);
174 +               if (err)
175 +                       dev_warn(sfp->dev, "hwmon probe failed: %d\n", err);
176 +       }
177 +#endif
178  }
179  
180  static void sfp_sm_main(struct sfp *sfp, unsigned int event)
181 @@ -2001,6 +2049,8 @@ static struct sfp *sfp_alloc(struct devi
182         INIT_DELAYED_WORK(&sfp->poll, sfp_poll);
183         INIT_DELAYED_WORK(&sfp->timeout, sfp_timeout);
184  
185 +       sfp_hwmon_init(sfp);
186 +
187         return sfp;
188  }
189  
190 @@ -2008,6 +2058,8 @@ static void sfp_cleanup(void *data)
191  {
192         struct sfp *sfp = data;
193  
194 +       sfp_hwmon_exit(sfp);
195 +
196         cancel_delayed_work_sync(&sfp->poll);
197         cancel_delayed_work_sync(&sfp->timeout);
198         if (sfp->i2c_mii) {