1e0e224c39d9b019ed5592233c00391144f3422e
[openwrt/staging/981213.git] /
1 From d7805757c75c76e9518fc1023a29f0c4eed5b581 Mon Sep 17 00:00:00 2001
2 From: Ansuel Smith <ansuelsmth@gmail.com>
3 Date: Fri, 14 May 2021 22:59:56 +0200
4 Subject: [PATCH] net: dsa: qca8k: handle error with qca8k_write operation
5
6 qca8k_write can fail. Rework any user to handle error values and
7 correctly return.
8
9 Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
10 Reviewed-by: Andrew Lunn <andrew@lunn.ch>
11 Signed-off-by: David S. Miller <davem@davemloft.net>
12 ---
13 drivers/net/dsa/qca8k.c | 102 ++++++++++++++++++++++++++--------------
14 1 file changed, 67 insertions(+), 35 deletions(-)
15
16 --- a/drivers/net/dsa/qca8k.c
17 +++ b/drivers/net/dsa/qca8k.c
18 @@ -168,7 +168,7 @@ exit:
19 return val;
20 }
21
22 -static void
23 +static int
24 qca8k_write(struct qca8k_priv *priv, u32 reg, u32 val)
25 {
26 struct mii_bus *bus = priv->bus;
27 @@ -187,6 +187,7 @@ qca8k_write(struct qca8k_priv *priv, u32
28
29 exit:
30 mutex_unlock(&bus->mdio_lock);
31 + return ret;
32 }
33
34 static u32
35 @@ -247,9 +248,7 @@ qca8k_regmap_write(void *ctx, uint32_t r
36 {
37 struct qca8k_priv *priv = (struct qca8k_priv *)ctx;
38
39 - qca8k_write(priv, reg, val);
40 -
41 - return 0;
42 + return qca8k_write(priv, reg, val);
43 }
44
45 static const struct regmap_range qca8k_readable_ranges[] = {
46 @@ -367,6 +366,7 @@ static int
47 qca8k_fdb_access(struct qca8k_priv *priv, enum qca8k_fdb_cmd cmd, int port)
48 {
49 u32 reg;
50 + int ret;
51
52 /* Set the command and FDB index */
53 reg = QCA8K_ATU_FUNC_BUSY;
54 @@ -377,7 +377,9 @@ qca8k_fdb_access(struct qca8k_priv *priv
55 }
56
57 /* Write the function register triggering the table access */
58 - qca8k_write(priv, QCA8K_REG_ATU_FUNC, reg);
59 + ret = qca8k_write(priv, QCA8K_REG_ATU_FUNC, reg);
60 + if (ret)
61 + return ret;
62
63 /* wait for completion */
64 if (qca8k_busy_wait(priv, QCA8K_REG_ATU_FUNC, QCA8K_ATU_FUNC_BUSY))
65 @@ -447,6 +449,7 @@ static int
66 qca8k_vlan_access(struct qca8k_priv *priv, enum qca8k_vlan_cmd cmd, u16 vid)
67 {
68 u32 reg;
69 + int ret;
70
71 /* Set the command and VLAN index */
72 reg = QCA8K_VTU_FUNC1_BUSY;
73 @@ -454,7 +457,9 @@ qca8k_vlan_access(struct qca8k_priv *pri
74 reg |= vid << QCA8K_VTU_FUNC1_VID_S;
75
76 /* Write the function register triggering the table access */
77 - qca8k_write(priv, QCA8K_REG_VTU_FUNC1, reg);
78 + ret = qca8k_write(priv, QCA8K_REG_VTU_FUNC1, reg);
79 + if (ret)
80 + return ret;
81
82 /* wait for completion */
83 if (qca8k_busy_wait(priv, QCA8K_REG_VTU_FUNC1, QCA8K_VTU_FUNC1_BUSY))
84 @@ -502,7 +507,9 @@ qca8k_vlan_add(struct qca8k_priv *priv,
85 reg |= QCA8K_VTU_FUNC0_EG_MODE_TAG <<
86 QCA8K_VTU_FUNC0_EG_MODE_S(port);
87
88 - qca8k_write(priv, QCA8K_REG_VTU_FUNC0, reg);
89 + ret = qca8k_write(priv, QCA8K_REG_VTU_FUNC0, reg);
90 + if (ret)
91 + return ret;
92 ret = qca8k_vlan_access(priv, QCA8K_VLAN_LOAD, vid);
93
94 out:
95 @@ -545,7 +552,9 @@ qca8k_vlan_del(struct qca8k_priv *priv,
96 if (del) {
97 ret = qca8k_vlan_access(priv, QCA8K_VLAN_PURGE, vid);
98 } else {
99 - qca8k_write(priv, QCA8K_REG_VTU_FUNC0, reg);
100 + ret = qca8k_write(priv, QCA8K_REG_VTU_FUNC0, reg);
101 + if (ret)
102 + return ret;
103 ret = qca8k_vlan_access(priv, QCA8K_VLAN_LOAD, vid);
104 }
105
106 @@ -555,15 +564,20 @@ out:
107 return ret;
108 }
109
110 -static void
111 +static int
112 qca8k_mib_init(struct qca8k_priv *priv)
113 {
114 + int ret;
115 +
116 mutex_lock(&priv->reg_mutex);
117 qca8k_reg_set(priv, QCA8K_REG_MIB, QCA8K_MIB_FLUSH | QCA8K_MIB_BUSY);
118 qca8k_busy_wait(priv, QCA8K_REG_MIB, QCA8K_MIB_BUSY);
119 qca8k_reg_set(priv, QCA8K_REG_MIB, QCA8K_MIB_CPU_KEEP);
120 - qca8k_write(priv, QCA8K_REG_MODULE_EN, QCA8K_MODULE_EN_MIB);
121 +
122 + ret = qca8k_write(priv, QCA8K_REG_MODULE_EN, QCA8K_MODULE_EN_MIB);
123 +
124 mutex_unlock(&priv->reg_mutex);
125 + return ret;
126 }
127
128 static void
129 @@ -600,6 +614,7 @@ static int
130 qca8k_mdio_write(struct qca8k_priv *priv, int port, u32 regnum, u16 data)
131 {
132 u32 phy, val;
133 + int ret;
134
135 if (regnum >= QCA8K_MDIO_MASTER_MAX_REG)
136 return -EINVAL;
137 @@ -613,7 +628,9 @@ qca8k_mdio_write(struct qca8k_priv *priv
138 QCA8K_MDIO_MASTER_REG_ADDR(regnum) |
139 QCA8K_MDIO_MASTER_DATA(data);
140
141 - qca8k_write(priv, QCA8K_MDIO_MASTER_CTRL, val);
142 + ret = qca8k_write(priv, QCA8K_MDIO_MASTER_CTRL, val);
143 + if (ret)
144 + return ret;
145
146 return qca8k_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL,
147 QCA8K_MDIO_MASTER_BUSY);
148 @@ -623,6 +640,7 @@ static int
149 qca8k_mdio_read(struct qca8k_priv *priv, int port, u32 regnum)
150 {
151 u32 phy, val;
152 + int ret;
153
154 if (regnum >= QCA8K_MDIO_MASTER_MAX_REG)
155 return -EINVAL;
156 @@ -635,7 +653,9 @@ qca8k_mdio_read(struct qca8k_priv *priv,
157 QCA8K_MDIO_MASTER_READ | QCA8K_MDIO_MASTER_PHY_ADDR(phy) |
158 QCA8K_MDIO_MASTER_REG_ADDR(regnum);
159
160 - qca8k_write(priv, QCA8K_MDIO_MASTER_CTRL, val);
161 + ret = qca8k_write(priv, QCA8K_MDIO_MASTER_CTRL, val);
162 + if (ret)
163 + return ret;
164
165 if (qca8k_busy_wait(priv, QCA8K_MDIO_MASTER_CTRL,
166 QCA8K_MDIO_MASTER_BUSY))
167 @@ -766,12 +786,18 @@ qca8k_setup(struct dsa_switch *ds)
168 QCA8K_GLOBAL_FW_CTRL0_CPU_PORT_EN);
169
170 /* Enable MIB counters */
171 - qca8k_mib_init(priv);
172 + ret = qca8k_mib_init(priv);
173 + if (ret)
174 + dev_warn(priv->dev, "mib init failed");
175
176 /* Enable QCA header mode on the cpu port */
177 - qca8k_write(priv, QCA8K_REG_PORT_HDR_CTRL(QCA8K_CPU_PORT),
178 - QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_TX_S |
179 - QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_RX_S);
180 + ret = qca8k_write(priv, QCA8K_REG_PORT_HDR_CTRL(QCA8K_CPU_PORT),
181 + QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_TX_S |
182 + QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_RX_S);
183 + if (ret) {
184 + dev_err(priv->dev, "failed enabling QCA header mode");
185 + return ret;
186 + }
187
188 /* Disable forwarding by default on all ports */
189 for (i = 0; i < QCA8K_NUM_PORTS; i++)
190 @@ -783,11 +809,13 @@ qca8k_setup(struct dsa_switch *ds)
191 qca8k_port_set_status(priv, i, 0);
192
193 /* Forward all unknown frames to CPU port for Linux processing */
194 - qca8k_write(priv, QCA8K_REG_GLOBAL_FW_CTRL1,
195 - BIT(0) << QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_S |
196 - BIT(0) << QCA8K_GLOBAL_FW_CTRL1_BC_DP_S |
197 - BIT(0) << QCA8K_GLOBAL_FW_CTRL1_MC_DP_S |
198 - BIT(0) << QCA8K_GLOBAL_FW_CTRL1_UC_DP_S);
199 + ret = qca8k_write(priv, QCA8K_REG_GLOBAL_FW_CTRL1,
200 + BIT(0) << QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_S |
201 + BIT(0) << QCA8K_GLOBAL_FW_CTRL1_BC_DP_S |
202 + BIT(0) << QCA8K_GLOBAL_FW_CTRL1_MC_DP_S |
203 + BIT(0) << QCA8K_GLOBAL_FW_CTRL1_UC_DP_S);
204 + if (ret)
205 + return ret;
206
207 /* Setup connection between CPU port & user ports */
208 for (i = 0; i < QCA8K_NUM_PORTS; i++) {
209 @@ -815,16 +843,20 @@ qca8k_setup(struct dsa_switch *ds)
210 qca8k_rmw(priv, QCA8K_EGRESS_VLAN(i),
211 0xfff << shift,
212 QCA8K_PORT_VID_DEF << shift);
213 - qca8k_write(priv, QCA8K_REG_PORT_VLAN_CTRL0(i),
214 - QCA8K_PORT_VLAN_CVID(QCA8K_PORT_VID_DEF) |
215 - QCA8K_PORT_VLAN_SVID(QCA8K_PORT_VID_DEF));
216 + ret = qca8k_write(priv, QCA8K_REG_PORT_VLAN_CTRL0(i),
217 + QCA8K_PORT_VLAN_CVID(QCA8K_PORT_VID_DEF) |
218 + QCA8K_PORT_VLAN_SVID(QCA8K_PORT_VID_DEF));
219 + if (ret)
220 + return ret;
221 }
222 }
223
224 /* Setup our port MTUs to match power on defaults */
225 for (i = 0; i < QCA8K_NUM_PORTS; i++)
226 priv->port_mtu[i] = ETH_FRAME_LEN + ETH_FCS_LEN;
227 - qca8k_write(priv, QCA8K_MAX_FRAME_SIZE, ETH_FRAME_LEN + ETH_FCS_LEN);
228 + ret = qca8k_write(priv, QCA8K_MAX_FRAME_SIZE, ETH_FRAME_LEN + ETH_FCS_LEN);
229 + if (ret)
230 + dev_warn(priv->dev, "failed setting MTU settings");
231
232 /* Flush the FDB table */
233 qca8k_fdb_flush(priv);
234 @@ -1140,8 +1172,8 @@ qca8k_set_mac_eee(struct dsa_switch *ds,
235 {
236 struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
237 u32 lpi_en = QCA8K_REG_EEE_CTRL_LPI_EN(port);
238 - int ret = 0;
239 u32 reg;
240 + int ret;
241
242 mutex_lock(&priv->reg_mutex);
243 reg = qca8k_read(priv, QCA8K_REG_EEE_CTRL);
244 @@ -1154,7 +1186,7 @@ qca8k_set_mac_eee(struct dsa_switch *ds,
245 reg |= lpi_en;
246 else
247 reg &= ~lpi_en;
248 - qca8k_write(priv, QCA8K_REG_EEE_CTRL, reg);
249 + ret = qca8k_write(priv, QCA8K_REG_EEE_CTRL, reg);
250
251 exit:
252 mutex_unlock(&priv->reg_mutex);
253 @@ -1284,9 +1316,7 @@ qca8k_port_change_mtu(struct dsa_switch
254 mtu = priv->port_mtu[i];
255
256 /* Include L2 header / FCS length */
257 - qca8k_write(priv, QCA8K_MAX_FRAME_SIZE, mtu + ETH_HLEN + ETH_FCS_LEN);
258 -
259 - return 0;
260 + return qca8k_write(priv, QCA8K_MAX_FRAME_SIZE, mtu + ETH_HLEN + ETH_FCS_LEN);
261 }
262
263 static int