generic: mt7530: fix null pointer dereferencing in port5 setup
[oweals/openwrt.git] / target / linux / generic / backport-5.4 / 744-v5.5-net-sfp-soft-status-and-control-support.patch
1 From 40e0b3b15f7da92e6b065292b14af7b9bfb1c6e0 Mon Sep 17 00:00:00 2001
2 From: Russell King <rmk+kernel@armlinux.org.uk>
3 Date: Fri, 13 Sep 2019 23:00:35 +0100
4 Subject: [PATCH 642/660] net: sfp: soft status and control support
5
6 Add support for the soft status and control register, which allows
7 TX_FAULT and RX_LOS to be monitored and TX_DISABLE to be set.  We
8 make use of this when the board does not support GPIOs for these
9 signals.
10
11 Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
12 ---
13  drivers/net/phy/sfp.c | 110 ++++++++++++++++++++++++++++++++++--------
14  include/linux/sfp.h   |   4 ++
15  2 files changed, 94 insertions(+), 20 deletions(-)
16
17 --- a/drivers/net/phy/sfp.c
18 +++ b/drivers/net/phy/sfp.c
19 @@ -201,7 +201,10 @@ struct sfp {
20         struct gpio_desc *gpio[GPIO_MAX];
21         int gpio_irq[GPIO_MAX];
22  
23 +       bool need_poll;
24 +
25         struct mutex st_mutex;                  /* Protects state */
26 +       unsigned int state_soft_mask;
27         unsigned int state;
28         struct delayed_work poll;
29         struct delayed_work timeout;
30 @@ -395,24 +398,90 @@ static int sfp_i2c_configure(struct sfp
31  }
32  
33  /* Interface */
34 -static unsigned int sfp_get_state(struct sfp *sfp)
35 +static int sfp_read(struct sfp *sfp, bool a2, u8 addr, void *buf, size_t len)
36  {
37 -       return sfp->get_state(sfp);
38 +       return sfp->read(sfp, a2, addr, buf, len);
39  }
40  
41 -static void sfp_set_state(struct sfp *sfp, unsigned int state)
42 +static int sfp_write(struct sfp *sfp, bool a2, u8 addr, void *buf, size_t len)
43  {
44 -       sfp->set_state(sfp, state);
45 +       return sfp->write(sfp, a2, addr, buf, len);
46  }
47  
48 -static int sfp_read(struct sfp *sfp, bool a2, u8 addr, void *buf, size_t len)
49 +static unsigned int sfp_soft_get_state(struct sfp *sfp)
50  {
51 -       return sfp->read(sfp, a2, addr, buf, len);
52 +       unsigned int state = 0;
53 +       u8 status;
54 +
55 +       if (sfp_read(sfp, true, SFP_STATUS, &status, sizeof(status)) ==
56 +                    sizeof(status)) {
57 +               if (status & SFP_STATUS_RX_LOS)
58 +                       state |= SFP_F_LOS;
59 +               if (status & SFP_STATUS_TX_FAULT)
60 +                       state |= SFP_F_TX_FAULT;
61 +       }
62 +
63 +       return state & sfp->state_soft_mask;
64  }
65  
66 -static int sfp_write(struct sfp *sfp, bool a2, u8 addr, void *buf, size_t len)
67 +static void sfp_soft_set_state(struct sfp *sfp, unsigned int state)
68  {
69 -       return sfp->write(sfp, a2, addr, buf, len);
70 +       u8 status;
71 +
72 +       if (sfp_read(sfp, true, SFP_STATUS, &status, sizeof(status)) ==
73 +                    sizeof(status)) {
74 +               if (state & SFP_F_TX_DISABLE)
75 +                       status |= SFP_STATUS_TX_DISABLE_FORCE;
76 +               else
77 +                       status &= ~SFP_STATUS_TX_DISABLE_FORCE;
78 +
79 +               sfp_write(sfp, true, SFP_STATUS, &status, sizeof(status));
80 +       }
81 +}
82 +
83 +static void sfp_soft_start_poll(struct sfp *sfp)
84 +{
85 +       const struct sfp_eeprom_id *id = &sfp->id;
86 +
87 +       sfp->state_soft_mask = 0;
88 +       if (id->ext.enhopts & SFP_ENHOPTS_SOFT_TX_DISABLE &&
89 +           !sfp->gpio[GPIO_TX_DISABLE])
90 +               sfp->state_soft_mask |= SFP_F_TX_DISABLE;
91 +       if (id->ext.enhopts & SFP_ENHOPTS_SOFT_TX_FAULT &&
92 +           !sfp->gpio[GPIO_TX_FAULT])
93 +               sfp->state_soft_mask |= SFP_F_TX_FAULT;
94 +       if (id->ext.enhopts & SFP_ENHOPTS_SOFT_RX_LOS &&
95 +           !sfp->gpio[GPIO_LOS])
96 +               sfp->state_soft_mask |= SFP_F_LOS;
97 +
98 +       if (sfp->state_soft_mask & (SFP_F_LOS | SFP_F_TX_FAULT) &&
99 +           !sfp->need_poll)
100 +               mod_delayed_work(system_wq, &sfp->poll, poll_jiffies);
101 +}
102 +
103 +static void sfp_soft_stop_poll(struct sfp *sfp)
104 +{
105 +       sfp->state_soft_mask = 0;
106 +}
107 +
108 +static unsigned int sfp_get_state(struct sfp *sfp)
109 +{
110 +       unsigned int state = sfp->get_state(sfp);
111 +
112 +       if (state & SFP_F_PRESENT &&
113 +           sfp->state_soft_mask & (SFP_F_LOS | SFP_F_TX_FAULT))
114 +               state |= sfp_soft_get_state(sfp);
115 +
116 +       return state;
117 +}
118 +
119 +static void sfp_set_state(struct sfp *sfp, unsigned int state)
120 +{
121 +       sfp->set_state(sfp, state);
122 +
123 +       if (state & SFP_F_PRESENT &&
124 +           sfp->state_soft_mask & SFP_F_TX_DISABLE)
125 +               sfp_soft_set_state(sfp, state);
126  }
127  
128  static unsigned int sfp_check(void *buf, size_t len)
129 @@ -1407,11 +1476,6 @@ static void sfp_sm_fault(struct sfp *sfp
130         }
131  }
132  
133 -static void sfp_sm_mod_init(struct sfp *sfp)
134 -{
135 -       sfp_module_tx_enable(sfp);
136 -}
137 -
138  static void sfp_sm_probe_for_phy(struct sfp *sfp)
139  {
140         /* Setting the serdes link mode is guesswork: there's no
141 @@ -1574,7 +1638,7 @@ static int sfp_sm_mod_probe(struct sfp *
142                  (int)sizeof(id.ext.datecode), id.ext.datecode);
143  
144         /* Check whether we support this module */
145 -       if (!sfp->type->module_supported(&sfp->id)) {
146 +       if (!sfp->type->module_supported(&id)) {
147                 dev_err(sfp->dev,
148                         "module is not supported - phys id 0x%02x 0x%02x\n",
149                         sfp->id.base.phys_id, sfp->id.base.phys_ext_id);
150 @@ -1764,6 +1828,7 @@ static void sfp_sm_main(struct sfp *sfp,
151                 if (sfp->mod_phy)
152                         sfp_sm_phy_detach(sfp);
153                 sfp_module_tx_disable(sfp);
154 +               sfp_soft_stop_poll(sfp);
155                 sfp_sm_next(sfp, SFP_S_DOWN, 0);
156                 return;
157         }
158 @@ -1775,7 +1840,10 @@ static void sfp_sm_main(struct sfp *sfp,
159                     sfp->sm_dev_state != SFP_DEV_UP)
160                         break;
161  
162 -               sfp_sm_mod_init(sfp);
163 +               if (!(sfp->id.ext.diagmon & SFP_DIAGMON_ADDRMODE))
164 +                       sfp_soft_start_poll(sfp);
165 +
166 +               sfp_module_tx_enable(sfp);
167  
168                 /* Initialise the fault clearance retries */
169                 sfp->sm_retries = 5;
170 @@ -2031,7 +2099,10 @@ static void sfp_poll(struct work_struct
171         struct sfp *sfp = container_of(work, struct sfp, poll.work);
172  
173         sfp_check_state(sfp);
174 -       mod_delayed_work(system_wq, &sfp->poll, poll_jiffies);
175 +
176 +       if (sfp->state_soft_mask & (SFP_F_LOS | SFP_F_TX_FAULT) ||
177 +           sfp->need_poll)
178 +               mod_delayed_work(system_wq, &sfp->poll, poll_jiffies);
179  }
180  
181  static struct sfp *sfp_alloc(struct device *dev)
182 @@ -2076,7 +2147,6 @@ static int sfp_probe(struct platform_dev
183         const struct sff_data *sff;
184         struct i2c_adapter *i2c;
185         struct sfp *sfp;
186 -       bool poll = false;
187         int err, i;
188  
189         sfp = sfp_alloc(&pdev->dev);
190 @@ -2183,7 +2253,7 @@ static int sfp_probe(struct platform_dev
191  
192                 sfp->gpio_irq[i] = gpiod_to_irq(sfp->gpio[i]);
193                 if (!sfp->gpio_irq[i]) {
194 -                       poll = true;
195 +                       sfp->need_poll = true;
196                         continue;
197                 }
198  
199 @@ -2195,11 +2265,11 @@ static int sfp_probe(struct platform_dev
200                                                 dev_name(sfp->dev), sfp);
201                 if (err) {
202                         sfp->gpio_irq[i] = 0;
203 -                       poll = true;
204 +                       sfp->need_poll = true;
205                 }
206         }
207  
208 -       if (poll)
209 +       if (sfp->need_poll)
210                 mod_delayed_work(system_wq, &sfp->poll, poll_jiffies);
211  
212         /* We could have an issue in cases no Tx disable pin is available or
213 --- a/include/linux/sfp.h
214 +++ b/include/linux/sfp.h
215 @@ -428,6 +428,10 @@ enum {
216         SFP_TEC_CUR                     = 0x6c,
217  
218         SFP_STATUS                      = 0x6e,
219 +       SFP_STATUS_TX_DISABLE           = BIT(7),
220 +       SFP_STATUS_TX_DISABLE_FORCE     = BIT(6),
221 +       SFP_STATUS_TX_FAULT             = BIT(2),
222 +       SFP_STATUS_RX_LOS               = BIT(1),
223         SFP_ALARM0                      = 0x70,
224         SFP_ALARM0_TEMP_HIGH            = BIT(7),
225         SFP_ALARM0_TEMP_LOW             = BIT(6),