1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Driver for MaxLinear MxL862xx switch family
4 *
5 * Copyright (C) 2024 MaxLinear Inc.
6 * Copyright (C) 2025 John Crispin <john@phrozen.org>
7 * Copyright (C) 2025 Daniel Golle <daniel@makrotopia.org>
8 */
9
10 #include <linux/bitfield.h>
11 #include <linux/delay.h>
12 #include <linux/etherdevice.h>
13 #include <linux/if_bridge.h>
14 #include <linux/module.h>
15 #include <linux/of_device.h>
16 #include <linux/of_mdio.h>
17 #include <linux/phy.h>
18 #include <linux/phylink.h>
19 #include <net/dsa.h>
20
21 #include "mxl862xx.h"
22 #include "mxl862xx-api.h"
23 #include "mxl862xx-cmd.h"
24 #include "mxl862xx-host.h"
25 #include "mxl862xx-phylink.h"
26
27 /* Polling interval for RMON counter accumulation. At 2.5 Gbps with
28 * minimum-size (64-byte) frames, a 32-bit packet counter wraps in ~880s.
29 * 2s gives a comfortable margin.
30 */
31 #define MXL862XX_STATS_POLL_INTERVAL (2 * HZ)
32
33 struct mxl862xx_mib_desc {
34 unsigned int size;
35 unsigned int offset;
36 const char *name;
37 };
38
39 #define MIB_DESC(_size, _name, _element) \
40 { \
41 .size = _size, \
42 .name = _name, \
43 .offset = offsetof(struct mxl862xx_rmon_port_cnt, _element) \
44 }
45
46 /* Hardware-specific counters not covered by any standardized stats callback. */
47 static const struct mxl862xx_mib_desc mxl862xx_mib[] = {
48 MIB_DESC(1, "TxAcmDroppedPkts", tx_acm_dropped_pkts),
49 MIB_DESC(1, "RxFilteredPkts", rx_filtered_pkts),
50 MIB_DESC(1, "RxExtendedVlanDiscardPkts", rx_extended_vlan_discard_pkts),
51 MIB_DESC(1, "MtuExceedDiscardPkts", mtu_exceed_discard_pkts),
52 MIB_DESC(2, "RxBadBytes", rx_bad_bytes),
53 };
54
55 static const struct ethtool_rmon_hist_range mxl862xx_rmon_ranges[] = {
56 { 0, 64 },
57 { 65, 127 },
58 { 128, 255 },
59 { 256, 511 },
60 { 512, 1023 },
61 { 1024, 10240 },
62 {}
63 };
64
65 #define MXL862XX_SDMA_PCTRLP(p) (0xbc0 + ((p) * 0x6))
66 #define MXL862XX_SDMA_PCTRL_EN BIT(0)
67
68 #define MXL862XX_FDMA_PCTRLP(p) (0xa80 + ((p) * 0x6))
69 #define MXL862XX_FDMA_PCTRL_EN BIT(0)
70
71 #define MXL862XX_READY_TIMEOUT_MS 10000
72 #define MXL862XX_READY_POLL_MS 100
73
74 #define MXL862XX_TCM_INST_SEL 0xe00
75 #define MXL862XX_TCM_CBS 0xe12
76 #define MXL862XX_TCM_EBS 0xe13
77
78 static const int mxl862xx_flood_meters[] = {
79 MXL862XX_BRIDGE_PORT_EGRESS_METER_UNKNOWN_UC,
80 MXL862XX_BRIDGE_PORT_EGRESS_METER_UNKNOWN_MC_IP,
81 MXL862XX_BRIDGE_PORT_EGRESS_METER_UNKNOWN_MC_NON_IP,
82 MXL862XX_BRIDGE_PORT_EGRESS_METER_BROADCAST,
83 };
84
85 enum mxl862xx_evlan_action {
86 EVLAN_ACCEPT, /* pass-through, no tag removal */
87 EVLAN_STRIP_IF_UNTAGGED, /* remove 1 tag if entry's untagged flag set */
88 EVLAN_PVID_OR_DISCARD, /* insert PVID tag or discard if no PVID */
89 EVLAN_STRIP1_AND_PVID_OR_DISCARD,/* strip 1 tag + insert PVID, or discard */
90 };
91
92 struct mxl862xx_evlan_rule_desc {
93 u8 outer_type; /* enum mxl862xx_extended_vlan_filter_type */
94 u8 inner_type; /* enum mxl862xx_extended_vlan_filter_type */
95 u8 outer_tpid; /* enum mxl862xx_extended_vlan_filter_tpid */
96 u8 inner_tpid; /* enum mxl862xx_extended_vlan_filter_tpid */
97 bool match_vid; /* true: match on VID from the vid parameter */
98 u8 action; /* enum mxl862xx_evlan_action */
99 };
100
101 /* Shorthand constants for readability */
102 #define FT_NORMAL MXL862XX_EXTENDEDVLAN_FILTER_TYPE_NORMAL
103 #define FT_NO_FILTER MXL862XX_EXTENDEDVLAN_FILTER_TYPE_NO_FILTER
104 #define FT_DEFAULT MXL862XX_EXTENDEDVLAN_FILTER_TYPE_DEFAULT
105 #define FT_NO_TAG MXL862XX_EXTENDEDVLAN_FILTER_TYPE_NO_TAG
106 #define TP_NONE MXL862XX_EXTENDEDVLAN_FILTER_TPID_NO_FILTER
107 #define TP_8021Q MXL862XX_EXTENDEDVLAN_FILTER_TPID_8021Q
108
109 /*
110 * VLAN-aware ingress: 7 final catchall rules.
111 *
112 * VLAN Filter handles VID membership for tagged frames, so the
113 * Extended VLAN ingress block only needs to handle:
114 * - Priority-tagged (VID=0): strip + insert PVID
115 * - Untagged: insert PVID or discard
116 * - Standard 802.1Q VID>0: pass through (VF handles membership)
117 * - Non-8021Q TPID (0x88A8 etc.): treat as untagged
118 *
119 * Rule ordering is critical: the EVLAN engine scans entries in
120 * ascending index order and stops at the first match.
121 *
122 * The 802.1Q ACCEPT rules (indices 3--4) must appear BEFORE the
123 * NO_FILTER catchalls (indices 5--6). NO_FILTER matches any tag
124 * regardless of TPID, so without the ACCEPT guard, it would also
125 * catch standard 802.1Q VID>0 frames and corrupt them. With the
126 * guard, 802.1Q VID>0 frames match the ACCEPT rules first and
127 * pass through untouched; only non-8021Q TPID frames pass through
128 * to the NO_FILTER catchalls.
129 */
130 static const struct mxl862xx_evlan_rule_desc ingress_aware_final[] = {
131 /* 802.1p / priority-tagged (VID 0): strip + PVID */
132 { FT_NORMAL, FT_NORMAL, TP_8021Q, TP_8021Q, true, EVLAN_STRIP1_AND_PVID_OR_DISCARD },
133 { FT_NORMAL, FT_NO_TAG, TP_8021Q, TP_NONE, true, EVLAN_STRIP1_AND_PVID_OR_DISCARD },
134 /* Untagged: PVID insertion or discard */
135 { FT_NO_TAG, FT_NO_TAG, TP_NONE, TP_NONE, false, EVLAN_PVID_OR_DISCARD },
136 /* 802.1Q VID>0: accept - VF handles membership.
137 * match_vid=false means any VID; VID=0 is already caught above.
138 */
139 { FT_NORMAL, FT_NORMAL, TP_8021Q, TP_8021Q, false, EVLAN_ACCEPT },
140 { FT_NORMAL, FT_NO_TAG, TP_8021Q, TP_NONE, false, EVLAN_ACCEPT },
141 /* Non-8021Q TPID (0x88A8 etc.): treat as untagged - strip + PVID */
142 { FT_NO_FILTER, FT_NO_FILTER, TP_NONE, TP_NONE, false, EVLAN_STRIP1_AND_PVID_OR_DISCARD },
143 { FT_NO_FILTER, FT_NO_TAG, TP_NONE, TP_NONE, false, EVLAN_STRIP1_AND_PVID_OR_DISCARD },
144 };
145
146 /*
147 * VID-specific accept rules (VLAN-aware, standard tag, 2 per VID).
148 * Outer tag carries the VLAN; inner may or may not be present.
149 */
150 static const struct mxl862xx_evlan_rule_desc vid_accept_standard[] = {
151 { FT_NORMAL, FT_NORMAL, TP_8021Q, TP_8021Q, true, EVLAN_STRIP_IF_UNTAGGED },
152 { FT_NORMAL, FT_NO_TAG, TP_8021Q, TP_NONE, true, EVLAN_STRIP_IF_UNTAGGED },
153 };
154
155 /*
156 * Egress tag-stripping rules for VLAN-unaware mode (2 per untagged VID).
157 * The HW sees the MxL tag as outer; the real VLAN tag, if any, is inner.
158 */
159 static const struct mxl862xx_evlan_rule_desc vid_accept_egress_unaware[] = {
160 { FT_NO_FILTER, FT_NORMAL, TP_NONE, TP_8021Q, true, EVLAN_STRIP_IF_UNTAGGED },
161 { FT_NO_FILTER, FT_NO_TAG, TP_NONE, TP_NONE, false, EVLAN_STRIP_IF_UNTAGGED },
162 };
163
mxl862xx_get_tag_protocol(struct dsa_switch * ds,int port,enum dsa_tag_protocol m)164 static enum dsa_tag_protocol mxl862xx_get_tag_protocol(struct dsa_switch *ds,
165 int port,
166 enum dsa_tag_protocol m)
167 {
168 return DSA_TAG_PROTO_MXL862;
169 }
170
171 /* PHY access via firmware relay */
mxl862xx_phy_read_mmd(struct mxl862xx_priv * priv,int addr,int devadd,int regnum)172 static int mxl862xx_phy_read_mmd(struct mxl862xx_priv *priv, int addr,
173 int devadd, int regnum)
174 {
175 struct mdio_relay_data param = {
176 .phy = addr,
177 .mmd = devadd,
178 .reg = cpu_to_le16(regnum),
179 };
180 int ret;
181
182 ret = MXL862XX_API_READ(priv, INT_GPHY_READ, param);
183 if (ret)
184 return ret;
185
186 return le16_to_cpu(param.data);
187 }
188
mxl862xx_phy_write_mmd(struct mxl862xx_priv * priv,int addr,int devadd,int regnum,u16 data)189 static int mxl862xx_phy_write_mmd(struct mxl862xx_priv *priv, int addr,
190 int devadd, int regnum, u16 data)
191 {
192 struct mdio_relay_data param = {
193 .phy = addr,
194 .mmd = devadd,
195 .reg = cpu_to_le16(regnum),
196 .data = cpu_to_le16(data),
197 };
198
199 return MXL862XX_API_WRITE(priv, INT_GPHY_WRITE, param);
200 }
201
mxl862xx_phy_read_mii_bus(struct mii_bus * bus,int addr,int regnum)202 static int mxl862xx_phy_read_mii_bus(struct mii_bus *bus, int addr, int regnum)
203 {
204 return mxl862xx_phy_read_mmd(bus->priv, addr, 0, regnum);
205 }
206
mxl862xx_phy_write_mii_bus(struct mii_bus * bus,int addr,int regnum,u16 val)207 static int mxl862xx_phy_write_mii_bus(struct mii_bus *bus, int addr,
208 int regnum, u16 val)
209 {
210 return mxl862xx_phy_write_mmd(bus->priv, addr, 0, regnum, val);
211 }
212
mxl862xx_phy_read_c45_mii_bus(struct mii_bus * bus,int addr,int devadd,int regnum)213 static int mxl862xx_phy_read_c45_mii_bus(struct mii_bus *bus, int addr,
214 int devadd, int regnum)
215 {
216 return mxl862xx_phy_read_mmd(bus->priv, addr, devadd, regnum);
217 }
218
mxl862xx_phy_write_c45_mii_bus(struct mii_bus * bus,int addr,int devadd,int regnum,u16 val)219 static int mxl862xx_phy_write_c45_mii_bus(struct mii_bus *bus, int addr,
220 int devadd, int regnum, u16 val)
221 {
222 return mxl862xx_phy_write_mmd(bus->priv, addr, devadd, regnum, val);
223 }
224
mxl862xx_wait_ready(struct dsa_switch * ds)225 static int mxl862xx_wait_ready(struct dsa_switch *ds)
226 {
227 struct mxl862xx_sys_fw_image_version ver = {};
228 unsigned long start = jiffies, timeout;
229 struct mxl862xx_priv *priv = ds->priv;
230 struct mxl862xx_cfg cfg = {};
231 int ret;
232
233 timeout = start + msecs_to_jiffies(MXL862XX_READY_TIMEOUT_MS);
234 msleep(2000); /* it always takes at least 2 seconds */
235 do {
236 ret = MXL862XX_API_READ_QUIET(priv, SYS_MISC_FW_VERSION, ver);
237 if (ret || !ver.iv_major)
238 goto not_ready_yet;
239
240 /* being able to perform CFGGET indicates that
241 * the firmware is ready
242 */
243 ret = MXL862XX_API_READ_QUIET(priv,
244 MXL862XX_COMMON_CFGGET,
245 cfg);
246 if (ret)
247 goto not_ready_yet;
248
249 dev_info(ds->dev, "switch ready after %ums, firmware %u.%u.%u (build %u)\n",
250 jiffies_to_msecs(jiffies - start),
251 ver.iv_major, ver.iv_minor,
252 le16_to_cpu(ver.iv_revision),
253 le32_to_cpu(ver.iv_build_num));
254 priv->fw_version.major = ver.iv_major;
255 priv->fw_version.minor = ver.iv_minor;
256 priv->fw_version.revision = le16_to_cpu(ver.iv_revision);
257 return 0;
258
259 not_ready_yet:
260 msleep(MXL862XX_READY_POLL_MS);
261 } while (time_before(jiffies, timeout));
262
263 dev_err(ds->dev, "switch not responding after reset\n");
264 return -ETIMEDOUT;
265 }
266
mxl862xx_setup_mdio(struct dsa_switch * ds)267 static int mxl862xx_setup_mdio(struct dsa_switch *ds)
268 {
269 struct mxl862xx_priv *priv = ds->priv;
270 struct device *dev = ds->dev;
271 struct device_node *mdio_np;
272 struct mii_bus *bus;
273 int ret;
274
275 bus = devm_mdiobus_alloc(dev);
276 if (!bus)
277 return -ENOMEM;
278
279 bus->priv = priv;
280 bus->name = KBUILD_MODNAME "-mii";
281 snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mii", dev_name(dev));
282 bus->read_c45 = mxl862xx_phy_read_c45_mii_bus;
283 bus->write_c45 = mxl862xx_phy_write_c45_mii_bus;
284 bus->read = mxl862xx_phy_read_mii_bus;
285 bus->write = mxl862xx_phy_write_mii_bus;
286 bus->parent = dev;
287 bus->phy_mask = ~ds->phys_mii_mask;
288
289 mdio_np = of_get_child_by_name(dev->of_node, "mdio");
290 if (!mdio_np)
291 return -ENODEV;
292
293 ret = devm_of_mdiobus_register(dev, bus, mdio_np);
294 of_node_put(mdio_np);
295
296 return ret;
297 }
298
mxl862xx_bridge_config_fwd(struct dsa_switch * ds,u16 bridge_id,bool ucast_flood,bool mcast_flood,bool bcast_flood)299 static int mxl862xx_bridge_config_fwd(struct dsa_switch *ds, u16 bridge_id,
300 bool ucast_flood, bool mcast_flood,
301 bool bcast_flood)
302 {
303 struct mxl862xx_bridge_config bridge_config = {};
304 struct mxl862xx_priv *priv = ds->priv;
305 int ret;
306
307 bridge_config.mask = cpu_to_le32(MXL862XX_BRIDGE_CONFIG_MASK_FORWARDING_MODE);
308 bridge_config.bridge_id = cpu_to_le16(bridge_id);
309
310 bridge_config.forward_unknown_unicast = cpu_to_le32(ucast_flood ?
311 MXL862XX_BRIDGE_FORWARD_FLOOD : MXL862XX_BRIDGE_FORWARD_DISCARD);
312
313 bridge_config.forward_unknown_multicast_ip = cpu_to_le32(mcast_flood ?
314 MXL862XX_BRIDGE_FORWARD_FLOOD : MXL862XX_BRIDGE_FORWARD_DISCARD);
315 bridge_config.forward_unknown_multicast_non_ip =
316 bridge_config.forward_unknown_multicast_ip;
317
318 bridge_config.forward_broadcast = cpu_to_le32(bcast_flood ?
319 MXL862XX_BRIDGE_FORWARD_FLOOD : MXL862XX_BRIDGE_FORWARD_DISCARD);
320
321 ret = MXL862XX_API_WRITE(priv, MXL862XX_BRIDGE_CONFIGSET, bridge_config);
322 if (ret)
323 dev_err(ds->dev, "failed to configure bridge %u forwarding: %d\n",
324 bridge_id, ret);
325
326 return ret;
327 }
328
329 /* Allocate a single zero-rate meter shared by all ports and flood types.
330 * All flood-blocking egress sub-meters point to this one meter so that any
331 * packet hitting this meter is unconditionally dropped.
332 *
333 * The firmware API requires CBS >= 64 (its bs2ls encoder clamps smaller
334 * values), so the meter is initially configured with CBS=EBS=64.
335 * A zero-rate bucket starts full at CBS bytes, which would let one packet
336 * through before the bucket empties. To eliminate this one-packet leak we
337 * override CBS and EBS to zero via direct register writes after the API call;
338 * the hardware accepts CBS=0 and immediately flags the bucket as exceeded,
339 * so no traffic can ever pass.
340 */
mxl862xx_setup_drop_meter(struct dsa_switch * ds)341 static int mxl862xx_setup_drop_meter(struct dsa_switch *ds)
342 {
343 struct mxl862xx_qos_meter_cfg meter = {};
344 struct mxl862xx_priv *priv = ds->priv;
345 struct mxl862xx_register_mod reg;
346 int ret;
347
348 /* meter_id=0 means auto-alloc */
349 ret = MXL862XX_API_READ(priv, MXL862XX_QOS_METERALLOC, meter);
350 if (ret)
351 return ret;
352
353 meter.enable = true;
354 meter.cbs = cpu_to_le32(64);
355 meter.ebs = cpu_to_le32(64);
356 snprintf(meter.meter_name, sizeof(meter.meter_name), "drop");
357
358 ret = MXL862XX_API_WRITE(priv, MXL862XX_QOS_METERCFGSET, meter);
359 if (ret)
360 return ret;
361
362 priv->drop_meter = le16_to_cpu(meter.meter_id);
363
364 /* Select the meter instance for subsequent TCM register access. */
365 reg.addr = cpu_to_le16(MXL862XX_TCM_INST_SEL);
366 reg.data = cpu_to_le16(priv->drop_meter);
367 reg.mask = cpu_to_le16(0xffff);
368 ret = MXL862XX_API_WRITE(priv, MXL862XX_COMMON_REGISTERMOD, reg);
369 if (ret)
370 return ret;
371
372 /* Zero CBS so the committed bucket starts empty (exceeded). */
373 reg.addr = cpu_to_le16(MXL862XX_TCM_CBS);
374 reg.data = 0;
375 ret = MXL862XX_API_WRITE(priv, MXL862XX_COMMON_REGISTERMOD, reg);
376 if (ret)
377 return ret;
378
379 /* Zero EBS so the excess bucket starts empty (exceeded). */
380 reg.addr = cpu_to_le16(MXL862XX_TCM_EBS);
381 return MXL862XX_API_WRITE(priv, MXL862XX_COMMON_REGISTERMOD, reg);
382 }
383
mxl862xx_set_bridge_port(struct dsa_switch * ds,int port)384 static int mxl862xx_set_bridge_port(struct dsa_switch *ds, int port)
385 {
386 struct mxl862xx_bridge_port_config br_port_cfg = {};
387 struct dsa_port *dp = dsa_to_port(ds, port);
388 struct mxl862xx_priv *priv = ds->priv;
389 struct mxl862xx_port *p = &priv->ports[port];
390 struct dsa_port *member_dp;
391 u16 bridge_id;
392 u16 vf_scan;
393 bool enable;
394 int i, idx;
395
396 if (dsa_port_is_unused(dp))
397 return 0;
398
399 if (dsa_port_is_cpu(dp)) {
400 dsa_switch_for_each_user_port(member_dp, ds) {
401 if (member_dp->cpu_dp->index != port)
402 continue;
403 mxl862xx_fw_portmap_set_bit(br_port_cfg.bridge_port_map,
404 member_dp->index);
405 }
406 } else if (dp->bridge) {
407 dsa_switch_for_each_bridge_member(member_dp, ds,
408 dp->bridge->dev) {
409 if (member_dp->index == port)
410 continue;
411 mxl862xx_fw_portmap_set_bit(br_port_cfg.bridge_port_map,
412 member_dp->index);
413 }
414 mxl862xx_fw_portmap_set_bit(br_port_cfg.bridge_port_map,
415 dp->cpu_dp->index);
416 } else {
417 mxl862xx_fw_portmap_set_bit(br_port_cfg.bridge_port_map,
418 dp->cpu_dp->index);
419 p->flood_block = 0;
420 p->learning = false;
421 }
422
423 bridge_id = dp->bridge ? priv->bridges[dp->bridge->num] : p->fid;
424
425 br_port_cfg.bridge_port_id = cpu_to_le16(port);
426 br_port_cfg.bridge_id = cpu_to_le16(bridge_id);
427 br_port_cfg.mask = cpu_to_le32(MXL862XX_BRIDGE_PORT_CONFIG_MASK_BRIDGE_ID |
428 MXL862XX_BRIDGE_PORT_CONFIG_MASK_BRIDGE_PORT_MAP |
429 MXL862XX_BRIDGE_PORT_CONFIG_MASK_MC_SRC_MAC_LEARNING |
430 MXL862XX_BRIDGE_PORT_CONFIG_MASK_EGRESS_SUB_METER |
431 MXL862XX_BRIDGE_PORT_CONFIG_MASK_INGRESS_VLAN |
432 MXL862XX_BRIDGE_PORT_CONFIG_MASK_EGRESS_VLAN |
433 MXL862XX_BRIDGE_PORT_CONFIG_MASK_INGRESS_VLAN_FILTER |
434 MXL862XX_BRIDGE_PORT_CONFIG_MASK_EGRESS_VLAN_FILTER1 |
435 MXL862XX_BRIDGE_PORT_CONFIG_MASK_VLAN_BASED_MAC_LEARNING);
436 br_port_cfg.src_mac_learning_disable = !p->learning;
437
438 /* Extended VLAN block assignments.
439 * Ingress: block_size is sent as-is (all entries are finals).
440 * Egress: n_active narrows the scan window to only the
441 * entries actually written by evlan_program_egress.
442 */
443 br_port_cfg.ingress_extended_vlan_enable = p->ingress_evlan.in_use;
444 br_port_cfg.ingress_extended_vlan_block_id =
445 cpu_to_le16(p->ingress_evlan.block_id);
446 br_port_cfg.ingress_extended_vlan_block_size =
447 cpu_to_le16(p->ingress_evlan.block_size);
448 br_port_cfg.egress_extended_vlan_enable = p->egress_evlan.in_use;
449 br_port_cfg.egress_extended_vlan_block_id =
450 cpu_to_le16(p->egress_evlan.block_id);
451 br_port_cfg.egress_extended_vlan_block_size =
452 cpu_to_le16(p->egress_evlan.n_active);
453
454 /* VLAN Filter block assignments (per-port).
455 * The block_size sent to the firmware narrows the HW scan
456 * window to [block_id, block_id + active_count), relying on
457 * discard_unmatched_tagged for frames outside that range.
458 * When active_count=0, send 1 to scan only the DISCARD
459 * sentinel at index 0 (block_size=0 would disable narrowing
460 * and scan the entire allocated block).
461 *
462 * The bridge check ensures VF is disabled when the port
463 * leaves the bridge, without needing to prematurely clear
464 * vlan_filtering (which the DSA framework handles later via
465 * port_vlan_filtering).
466 */
467 if (p->vf.allocated && p->vlan_filtering &&
468 dsa_port_bridge_dev_get(dp)) {
469 vf_scan = max_t(u16, p->vf.active_count, 1);
470 br_port_cfg.ingress_vlan_filter_enable = 1;
471 br_port_cfg.ingress_vlan_filter_block_id =
472 cpu_to_le16(p->vf.block_id);
473 br_port_cfg.ingress_vlan_filter_block_size =
474 cpu_to_le16(vf_scan);
475
476 br_port_cfg.egress_vlan_filter1enable = 1;
477 br_port_cfg.egress_vlan_filter1block_id =
478 cpu_to_le16(p->vf.block_id);
479 br_port_cfg.egress_vlan_filter1block_size =
480 cpu_to_le16(vf_scan);
481 } else {
482 br_port_cfg.ingress_vlan_filter_enable = 0;
483 br_port_cfg.egress_vlan_filter1enable = 0;
484 }
485
486 /* IVL when VLAN-aware: include VID in FDB lookup keys so that
487 * learned entries are per-VID. In VLAN-unaware mode, SVL is
488 * used (VID excluded from key).
489 */
490 br_port_cfg.vlan_src_mac_vid_enable = p->vlan_filtering;
491 br_port_cfg.vlan_dst_mac_vid_enable = p->vlan_filtering;
492
493 for (i = 0; i < ARRAY_SIZE(mxl862xx_flood_meters); i++) {
494 idx = mxl862xx_flood_meters[i];
495 enable = !!(p->flood_block & BIT(idx));
496
497 br_port_cfg.egress_traffic_sub_meter_id[idx] =
498 enable ? cpu_to_le16(priv->drop_meter) : 0;
499 br_port_cfg.egress_sub_metering_enable[idx] = enable;
500 }
501
502 return MXL862XX_API_WRITE(priv, MXL862XX_BRIDGEPORT_CONFIGSET,
503 br_port_cfg);
504 }
505
mxl862xx_sync_bridge_members(struct dsa_switch * ds,const struct dsa_bridge * bridge)506 static int mxl862xx_sync_bridge_members(struct dsa_switch *ds,
507 const struct dsa_bridge *bridge)
508 {
509 struct dsa_port *dp;
510 int ret = 0, err;
511
512 dsa_switch_for_each_bridge_member(dp, ds, bridge->dev) {
513 err = mxl862xx_set_bridge_port(ds, dp->index);
514 if (err)
515 ret = err;
516 }
517
518 return ret;
519 }
520
mxl862xx_evlan_block_alloc(struct mxl862xx_priv * priv,struct mxl862xx_evlan_block * blk)521 static int mxl862xx_evlan_block_alloc(struct mxl862xx_priv *priv,
522 struct mxl862xx_evlan_block *blk)
523 {
524 struct mxl862xx_extendedvlan_alloc param = {};
525 int ret;
526
527 param.number_of_entries = cpu_to_le16(blk->block_size);
528
529 ret = MXL862XX_API_READ(priv, MXL862XX_EXTENDEDVLAN_ALLOC, param);
530 if (ret)
531 return ret;
532
533 blk->block_id = le16_to_cpu(param.extended_vlan_block_id);
534 blk->allocated = true;
535
536 return 0;
537 }
538
mxl862xx_vf_block_alloc(struct mxl862xx_priv * priv,u16 size,u16 * block_id)539 static int mxl862xx_vf_block_alloc(struct mxl862xx_priv *priv,
540 u16 size, u16 *block_id)
541 {
542 struct mxl862xx_vlanfilter_alloc param = {};
543 int ret;
544
545 param.number_of_entries = cpu_to_le16(size);
546 param.discard_untagged = 0;
547 param.discard_unmatched_tagged = 1;
548
549 ret = MXL862XX_API_READ(priv, MXL862XX_VLANFILTER_ALLOC, param);
550 if (ret)
551 return ret;
552
553 *block_id = le16_to_cpu(param.vlan_filter_block_id);
554 return 0;
555 }
556
mxl862xx_vf_entry_discard(struct mxl862xx_priv * priv,u16 block_id,u16 index)557 static int mxl862xx_vf_entry_discard(struct mxl862xx_priv *priv,
558 u16 block_id, u16 index)
559 {
560 struct mxl862xx_vlanfilter_config cfg = {};
561
562 cfg.vlan_filter_block_id = cpu_to_le16(block_id);
563 cfg.entry_index = cpu_to_le16(index);
564 cfg.vlan_filter_mask = cpu_to_le32(MXL862XX_VLAN_FILTER_TCI_MASK_VID);
565 cfg.val = cpu_to_le32(0);
566 cfg.discard_matched = 1;
567
568 return MXL862XX_API_WRITE(priv, MXL862XX_VLANFILTER_SET, cfg);
569 }
570
mxl862xx_vf_alloc(struct mxl862xx_priv * priv,struct mxl862xx_vf_block * vf)571 static int mxl862xx_vf_alloc(struct mxl862xx_priv *priv,
572 struct mxl862xx_vf_block *vf)
573 {
574 int ret;
575
576 ret = mxl862xx_vf_block_alloc(priv, vf->block_size, &vf->block_id);
577 if (ret)
578 return ret;
579
580 vf->allocated = true;
581 vf->active_count = 0;
582
583 /* Sentinel: block VID-0 when scan window covers only index 0 */
584 return mxl862xx_vf_entry_discard(priv, vf->block_id, 0);
585 }
586
mxl862xx_allocate_bridge(struct mxl862xx_priv * priv)587 static int mxl862xx_allocate_bridge(struct mxl862xx_priv *priv)
588 {
589 struct mxl862xx_bridge_alloc br_alloc = {};
590 int ret;
591
592 ret = MXL862XX_API_READ(priv, MXL862XX_BRIDGE_ALLOC, br_alloc);
593 if (ret)
594 return ret;
595
596 return le16_to_cpu(br_alloc.bridge_id);
597 }
598
mxl862xx_free_bridge(struct dsa_switch * ds,const struct dsa_bridge * bridge)599 static void mxl862xx_free_bridge(struct dsa_switch *ds,
600 const struct dsa_bridge *bridge)
601 {
602 struct mxl862xx_priv *priv = ds->priv;
603 u16 fw_id = priv->bridges[bridge->num];
604 struct mxl862xx_bridge_alloc br_alloc = {
605 .bridge_id = cpu_to_le16(fw_id),
606 };
607 int ret;
608
609 ret = MXL862XX_API_WRITE(priv, MXL862XX_BRIDGE_FREE, br_alloc);
610 if (ret) {
611 dev_err(ds->dev, "failed to free fw bridge %u: %pe\n",
612 fw_id, ERR_PTR(ret));
613 return;
614 }
615
616 priv->bridges[bridge->num] = 0;
617 }
618
mxl862xx_setup(struct dsa_switch * ds)619 static int mxl862xx_setup(struct dsa_switch *ds)
620 {
621 struct mxl862xx_priv *priv = ds->priv;
622 int n_user_ports = 0, max_vlans;
623 int ingress_finals, vid_rules;
624 struct dsa_port *dp;
625 int ret, i;
626
627 ret = mxl862xx_reset(priv);
628 if (ret)
629 return ret;
630
631 ret = mxl862xx_wait_ready(ds);
632 if (ret)
633 return ret;
634
635 mutex_init(&priv->serdes_lock);
636 for (i = 0; i < ARRAY_SIZE(priv->serdes_ports); i++)
637 mxl862xx_setup_pcs(priv, &priv->serdes_ports[i],
638 i + MXL862XX_FIRST_SERDES_PORT);
639
640 /* Calculate Extended VLAN block sizes.
641 * With VLAN Filter handling VID membership checks:
642 * Ingress: only final catchall rules (PVID insertion, 802.1Q
643 * accept, non-8021Q TPID handling, discard).
644 * Block sized to exactly fit the finals -- no per-VID
645 * ingress EVLAN rules are needed. (7 entries.)
646 * Egress: 2 rules per VID that needs tag stripping (untagged VIDs).
647 * No egress final catchalls -- VLAN Filter does the discard.
648 * CPU: EVLAN is left disabled on CPU ports -- frames pass
649 * through without EVLAN processing.
650 *
651 * Total EVLAN budget:
652 * n_user_ports * (ingress + egress) <= 1024.
653 * Ingress blocks are small (7 entries), so almost all capacity
654 * goes to egress VID rules.
655 */
656 dsa_switch_for_each_user_port(dp, ds)
657 n_user_ports++;
658
659 if (n_user_ports) {
660 ingress_finals = ARRAY_SIZE(ingress_aware_final);
661 vid_rules = ARRAY_SIZE(vid_accept_standard);
662
663 /* Ingress block: fixed at finals count (7 entries) */
664 priv->evlan_ingress_size = ingress_finals;
665
666 /* Egress block: remaining budget divided equally among
667 * user ports. Each untagged VID needs vid_rules (2)
668 * EVLAN entries for tag stripping. Tagged-only VIDs
669 * need no EVLAN rules at all.
670 */
671 max_vlans = (MXL862XX_TOTAL_EVLAN_ENTRIES -
672 n_user_ports * ingress_finals) /
673 (n_user_ports * vid_rules);
674 priv->evlan_egress_size = vid_rules * max_vlans;
675
676 /* VLAN Filter block: one per user port. The 1024-entry
677 * table is divided equally among user ports. Each port
678 * gets its own VF block for per-port VID membership --
679 * discard_unmatched_tagged handles the rest.
680 */
681 priv->vf_block_size = MXL862XX_TOTAL_VF_ENTRIES / n_user_ports;
682 }
683
684 ret = mxl862xx_setup_drop_meter(ds);
685 if (ret)
686 return ret;
687
688 ret = mxl862xx_setup_mdio(ds);
689 if (ret)
690 return ret;
691
692 schedule_delayed_work(&priv->stats_work,
693 MXL862XX_STATS_POLL_INTERVAL);
694
695 return 0;
696 }
697
mxl862xx_teardown(struct dsa_switch * ds)698 static void mxl862xx_teardown(struct dsa_switch *ds)
699 {
700 struct mxl862xx_priv *priv = ds->priv;
701
702 set_bit(MXL862XX_FLAG_WORK_STOPPED, &priv->flags);
703 disable_delayed_work_sync(&priv->stats_work);
704 }
705
mxl862xx_port_state(struct dsa_switch * ds,int port,bool enable)706 static int mxl862xx_port_state(struct dsa_switch *ds, int port, bool enable)
707 {
708 struct mxl862xx_register_mod sdma = {
709 .addr = cpu_to_le16(MXL862XX_SDMA_PCTRLP(port)),
710 .data = cpu_to_le16(enable ? MXL862XX_SDMA_PCTRL_EN : 0),
711 .mask = cpu_to_le16(MXL862XX_SDMA_PCTRL_EN),
712 };
713 struct mxl862xx_register_mod fdma = {
714 .addr = cpu_to_le16(MXL862XX_FDMA_PCTRLP(port)),
715 .data = cpu_to_le16(enable ? MXL862XX_FDMA_PCTRL_EN : 0),
716 .mask = cpu_to_le16(MXL862XX_FDMA_PCTRL_EN),
717 };
718 int ret;
719
720 ret = MXL862XX_API_WRITE(ds->priv, MXL862XX_COMMON_REGISTERMOD, sdma);
721 if (ret)
722 return ret;
723
724 return MXL862XX_API_WRITE(ds->priv, MXL862XX_COMMON_REGISTERMOD, fdma);
725 }
726
mxl862xx_port_enable(struct dsa_switch * ds,int port,struct phy_device * phydev)727 static int mxl862xx_port_enable(struct dsa_switch *ds, int port,
728 struct phy_device *phydev)
729 {
730 return mxl862xx_port_state(ds, port, true);
731 }
732
mxl862xx_port_disable(struct dsa_switch * ds,int port)733 static void mxl862xx_port_disable(struct dsa_switch *ds, int port)
734 {
735 if (mxl862xx_port_state(ds, port, false))
736 dev_err(ds->dev, "failed to disable port %d\n", port);
737 }
738
mxl862xx_port_fast_age(struct dsa_switch * ds,int port)739 static void mxl862xx_port_fast_age(struct dsa_switch *ds, int port)
740 {
741 struct mxl862xx_mac_table_clear param = {
742 .type = MXL862XX_MAC_CLEAR_PHY_PORT,
743 .port_id = port,
744 };
745
746 if (MXL862XX_API_WRITE(ds->priv, MXL862XX_MAC_TABLECLEARCOND, param))
747 dev_err(ds->dev, "failed to clear fdb on port %d\n", port);
748 }
749
mxl862xx_configure_ctp_port(struct dsa_switch * ds,int port,u16 first_ctp_port_id,u16 number_of_ctp_ports)750 static int mxl862xx_configure_ctp_port(struct dsa_switch *ds, int port,
751 u16 first_ctp_port_id,
752 u16 number_of_ctp_ports)
753 {
754 struct mxl862xx_ctp_port_assignment ctp_assign = {
755 .logical_port_id = port,
756 .first_ctp_port_id = cpu_to_le16(first_ctp_port_id),
757 .number_of_ctp_port = cpu_to_le16(number_of_ctp_ports),
758 .mode = cpu_to_le32(MXL862XX_LOGICAL_PORT_ETHERNET),
759 };
760
761 return MXL862XX_API_WRITE(ds->priv, MXL862XX_CTP_PORTASSIGNMENTSET,
762 ctp_assign);
763 }
764
mxl862xx_configure_sp_tag_proto(struct dsa_switch * ds,int port,bool enable)765 static int mxl862xx_configure_sp_tag_proto(struct dsa_switch *ds, int port,
766 bool enable)
767 {
768 struct mxl862xx_ss_sp_tag tag = {
769 .pid = port,
770 .mask = MXL862XX_SS_SP_TAG_MASK_RX | MXL862XX_SS_SP_TAG_MASK_TX,
771 .rx = enable ? MXL862XX_SS_SP_TAG_RX_TAG_NO_INSERT :
772 MXL862XX_SS_SP_TAG_RX_NO_TAG_INSERT,
773 .tx = enable ? MXL862XX_SS_SP_TAG_TX_TAG_NO_REMOVE :
774 MXL862XX_SS_SP_TAG_TX_TAG_REMOVE,
775 };
776
777 return MXL862XX_API_WRITE(ds->priv, MXL862XX_SS_SPTAG_SET, tag);
778 }
779
mxl862xx_evlan_write_rule(struct mxl862xx_priv * priv,u16 block_id,u16 entry_index,const struct mxl862xx_evlan_rule_desc * desc,u16 vid,bool untagged,u16 pvid)780 static int mxl862xx_evlan_write_rule(struct mxl862xx_priv *priv,
781 u16 block_id, u16 entry_index,
782 const struct mxl862xx_evlan_rule_desc *desc,
783 u16 vid, bool untagged, u16 pvid)
784 {
785 struct mxl862xx_extendedvlan_config cfg = {};
786 struct mxl862xx_extendedvlan_filter_vlan *fv;
787
788 cfg.extended_vlan_block_id = cpu_to_le16(block_id);
789 cfg.entry_index = cpu_to_le16(entry_index);
790
791 /* Populate filter */
792 cfg.filter.outer_vlan.type = cpu_to_le32(desc->outer_type);
793 cfg.filter.inner_vlan.type = cpu_to_le32(desc->inner_type);
794 cfg.filter.outer_vlan.tpid = cpu_to_le32(desc->outer_tpid);
795 cfg.filter.inner_vlan.tpid = cpu_to_le32(desc->inner_tpid);
796
797 if (desc->match_vid) {
798 /* For egress unaware: outer=NO_FILTER, match on inner tag */
799 if (desc->outer_type == FT_NO_FILTER)
800 fv = &cfg.filter.inner_vlan;
801 else
802 fv = &cfg.filter.outer_vlan;
803
804 fv->vid_enable = 1;
805 fv->vid_val = cpu_to_le32(vid);
806 }
807
808 /* Populate treatment based on action */
809 switch (desc->action) {
810 case EVLAN_ACCEPT:
811 cfg.treatment.remove_tag =
812 cpu_to_le32(MXL862XX_EXTENDEDVLAN_TREATMENT_NOT_REMOVE_TAG);
813 break;
814
815 case EVLAN_STRIP_IF_UNTAGGED:
816 cfg.treatment.remove_tag = cpu_to_le32(untagged ?
817 MXL862XX_EXTENDEDVLAN_TREATMENT_REMOVE_1_TAG :
818 MXL862XX_EXTENDEDVLAN_TREATMENT_NOT_REMOVE_TAG);
819 break;
820
821 case EVLAN_PVID_OR_DISCARD:
822 if (pvid) {
823 cfg.treatment.remove_tag =
824 cpu_to_le32(MXL862XX_EXTENDEDVLAN_TREATMENT_NOT_REMOVE_TAG);
825 cfg.treatment.add_outer_vlan = 1;
826 cfg.treatment.outer_vlan.vid_mode =
827 cpu_to_le32(MXL862XX_EXTENDEDVLAN_TREATMENT_VID_VAL);
828 cfg.treatment.outer_vlan.vid_val = cpu_to_le32(pvid);
829 cfg.treatment.outer_vlan.tpid =
830 cpu_to_le32(MXL862XX_EXTENDEDVLAN_TREATMENT_8021Q);
831 } else {
832 cfg.treatment.remove_tag =
833 cpu_to_le32(MXL862XX_EXTENDEDVLAN_TREATMENT_DISCARD_UPSTREAM);
834 }
835 break;
836
837 case EVLAN_STRIP1_AND_PVID_OR_DISCARD:
838 if (pvid) {
839 cfg.treatment.remove_tag =
840 cpu_to_le32(MXL862XX_EXTENDEDVLAN_TREATMENT_REMOVE_1_TAG);
841 cfg.treatment.add_outer_vlan = 1;
842 cfg.treatment.outer_vlan.vid_mode =
843 cpu_to_le32(MXL862XX_EXTENDEDVLAN_TREATMENT_VID_VAL);
844 cfg.treatment.outer_vlan.vid_val = cpu_to_le32(pvid);
845 cfg.treatment.outer_vlan.tpid =
846 cpu_to_le32(MXL862XX_EXTENDEDVLAN_TREATMENT_8021Q);
847 } else {
848 cfg.treatment.remove_tag =
849 cpu_to_le32(MXL862XX_EXTENDEDVLAN_TREATMENT_DISCARD_UPSTREAM);
850 }
851 break;
852 }
853
854 return MXL862XX_API_WRITE(priv, MXL862XX_EXTENDEDVLAN_SET, cfg);
855 }
856
mxl862xx_evlan_deactivate_entry(struct mxl862xx_priv * priv,u16 block_id,u16 entry_index)857 static int mxl862xx_evlan_deactivate_entry(struct mxl862xx_priv *priv,
858 u16 block_id, u16 entry_index)
859 {
860 struct mxl862xx_extendedvlan_config cfg = {};
861
862 cfg.extended_vlan_block_id = cpu_to_le16(block_id);
863 cfg.entry_index = cpu_to_le16(entry_index);
864
865 /* Use an unreachable filter (DEFAULT+DEFAULT) with DISCARD treatment.
866 * A zeroed entry would have NORMAL+NORMAL filter which matches
867 * real double-tagged traffic and passes it through.
868 */
869 cfg.filter.outer_vlan.type =
870 cpu_to_le32(MXL862XX_EXTENDEDVLAN_FILTER_TYPE_DEFAULT);
871 cfg.filter.inner_vlan.type =
872 cpu_to_le32(MXL862XX_EXTENDEDVLAN_FILTER_TYPE_DEFAULT);
873 cfg.treatment.remove_tag =
874 cpu_to_le32(MXL862XX_EXTENDEDVLAN_TREATMENT_DISCARD_UPSTREAM);
875
876 return MXL862XX_API_WRITE(priv, MXL862XX_EXTENDEDVLAN_SET, cfg);
877 }
878
mxl862xx_evlan_write_final_rules(struct mxl862xx_priv * priv,struct mxl862xx_evlan_block * blk,const struct mxl862xx_evlan_rule_desc * rules,int n_rules,u16 pvid)879 static int mxl862xx_evlan_write_final_rules(struct mxl862xx_priv *priv,
880 struct mxl862xx_evlan_block *blk,
881 const struct mxl862xx_evlan_rule_desc *rules,
882 int n_rules, u16 pvid)
883 {
884 u16 start_idx = blk->block_size - n_rules;
885 int i, ret;
886
887 for (i = 0; i < n_rules; i++) {
888 ret = mxl862xx_evlan_write_rule(priv, blk->block_id,
889 start_idx + i, &rules[i],
890 0, false, pvid);
891 if (ret)
892 return ret;
893 }
894
895 return 0;
896 }
897
mxl862xx_vf_entry_set(struct mxl862xx_priv * priv,u16 block_id,u16 index,u16 vid)898 static int mxl862xx_vf_entry_set(struct mxl862xx_priv *priv,
899 u16 block_id, u16 index, u16 vid)
900 {
901 struct mxl862xx_vlanfilter_config cfg = {};
902
903 cfg.vlan_filter_block_id = cpu_to_le16(block_id);
904 cfg.entry_index = cpu_to_le16(index);
905 cfg.vlan_filter_mask = cpu_to_le32(MXL862XX_VLAN_FILTER_TCI_MASK_VID);
906 cfg.val = cpu_to_le32(vid);
907 cfg.discard_matched = 0;
908
909 return MXL862XX_API_WRITE(priv, MXL862XX_VLANFILTER_SET, cfg);
910 }
911
mxl862xx_vf_find_vid(struct mxl862xx_vf_block * vf,u16 vid)912 static struct mxl862xx_vf_vid *mxl862xx_vf_find_vid(struct mxl862xx_vf_block *vf,
913 u16 vid)
914 {
915 struct mxl862xx_vf_vid *ve;
916
917 list_for_each_entry(ve, &vf->vids, list)
918 if (ve->vid == vid)
919 return ve;
920
921 return NULL;
922 }
923
mxl862xx_vf_add_vid(struct mxl862xx_priv * priv,struct mxl862xx_vf_block * vf,u16 vid,bool untagged)924 static int mxl862xx_vf_add_vid(struct mxl862xx_priv *priv,
925 struct mxl862xx_vf_block *vf,
926 u16 vid, bool untagged)
927 {
928 struct mxl862xx_vf_vid *ve;
929 int ret;
930
931 ve = mxl862xx_vf_find_vid(vf, vid);
932 if (ve) {
933 ve->untagged = untagged;
934 return 0;
935 }
936
937 if (vf->active_count >= vf->block_size)
938 return -ENOSPC;
939
940 ve = kzalloc_obj(*ve);
941 if (!ve)
942 return -ENOMEM;
943
944 ve->vid = vid;
945 ve->index = vf->active_count;
946 ve->untagged = untagged;
947
948 ret = mxl862xx_vf_entry_set(priv, vf->block_id, ve->index, vid);
949 if (ret) {
950 kfree(ve);
951 return ret;
952 }
953
954 list_add_tail(&ve->list, &vf->vids);
955 vf->active_count++;
956
957 return 0;
958 }
959
mxl862xx_vf_del_vid(struct mxl862xx_priv * priv,struct mxl862xx_vf_block * vf,u16 vid)960 static int mxl862xx_vf_del_vid(struct mxl862xx_priv *priv,
961 struct mxl862xx_vf_block *vf, u16 vid)
962 {
963 struct mxl862xx_vf_vid *ve, *last_ve;
964 u16 gap, last;
965 int ret;
966
967 ve = mxl862xx_vf_find_vid(vf, vid);
968 if (!ve)
969 return 0;
970
971 if (!vf->allocated) {
972 /* Software-only state -- just remove the tracking entry */
973 list_del(&ve->list);
974 kfree(ve);
975 vf->active_count--;
976 return 0;
977 }
978
979 gap = ve->index;
980 last = vf->active_count - 1;
981
982 if (vf->active_count == 1) {
983 /* Last VID -- restore DISCARD sentinel at index 0 */
984 ret = mxl862xx_vf_entry_discard(priv, vf->block_id, 0);
985 if (ret)
986 return ret;
987 } else if (gap < last) {
988 /* Swap: move the last ALLOW entry into the gap */
989 list_for_each_entry(last_ve, &vf->vids, list)
990 if (last_ve->index == last)
991 break;
992
993 if (WARN_ON(list_entry_is_head(last_ve, &vf->vids, list)))
994 return -EINVAL;
995
996 ret = mxl862xx_vf_entry_set(priv, vf->block_id,
997 gap, last_ve->vid);
998 if (ret)
999 return ret;
1000
1001 last_ve->index = gap;
1002 }
1003
1004 list_del(&ve->list);
1005 kfree(ve);
1006 vf->active_count--;
1007
1008 return 0;
1009 }
1010
mxl862xx_evlan_program_ingress(struct mxl862xx_priv * priv,int port)1011 static int mxl862xx_evlan_program_ingress(struct mxl862xx_priv *priv, int port)
1012 {
1013 struct mxl862xx_port *p = &priv->ports[port];
1014 struct mxl862xx_evlan_block *blk = &p->ingress_evlan;
1015
1016 if (!p->vlan_filtering)
1017 return 0;
1018
1019 blk->in_use = true;
1020 blk->n_active = blk->block_size;
1021
1022 return mxl862xx_evlan_write_final_rules(priv, blk,
1023 ingress_aware_final,
1024 ARRAY_SIZE(ingress_aware_final),
1025 p->pvid);
1026 }
1027
mxl862xx_evlan_program_egress(struct mxl862xx_priv * priv,int port)1028 static int mxl862xx_evlan_program_egress(struct mxl862xx_priv *priv, int port)
1029 {
1030 struct mxl862xx_port *p = &priv->ports[port];
1031 struct mxl862xx_evlan_block *blk = &p->egress_evlan;
1032 const struct mxl862xx_evlan_rule_desc *vid_rules;
1033 struct mxl862xx_vf_vid *vfv;
1034 u16 old_active = blk->n_active;
1035 u16 idx = 0, i;
1036 int n_vid, ret;
1037
1038 if (p->vlan_filtering) {
1039 vid_rules = vid_accept_standard;
1040 n_vid = ARRAY_SIZE(vid_accept_standard);
1041 } else {
1042 vid_rules = vid_accept_egress_unaware;
1043 n_vid = ARRAY_SIZE(vid_accept_egress_unaware);
1044 }
1045
1046 list_for_each_entry(vfv, &p->vf.vids, list) {
1047 if (!vfv->untagged)
1048 continue;
1049
1050 if (idx + n_vid > blk->block_size)
1051 return -ENOSPC;
1052
1053 ret = mxl862xx_evlan_write_rule(priv, blk->block_id,
1054 idx++, &vid_rules[0],
1055 vfv->vid, vfv->untagged,
1056 p->pvid);
1057 if (ret)
1058 return ret;
1059
1060 if (n_vid > 1) {
1061 ret = mxl862xx_evlan_write_rule(priv, blk->block_id,
1062 idx++, &vid_rules[1],
1063 vfv->vid,
1064 vfv->untagged,
1065 p->pvid);
1066 if (ret)
1067 return ret;
1068 }
1069 }
1070
1071 /* Deactivate stale entries that are no longer needed.
1072 * This closes the brief window between writing the new rules
1073 * and set_bridge_port narrowing the scan window.
1074 */
1075 for (i = idx; i < old_active; i++) {
1076 ret = mxl862xx_evlan_deactivate_entry(priv,
1077 blk->block_id,
1078 i);
1079 if (ret)
1080 return ret;
1081 }
1082
1083 blk->n_active = idx;
1084 blk->in_use = idx > 0;
1085
1086 return 0;
1087 }
1088
mxl862xx_port_vlan_filtering(struct dsa_switch * ds,int port,bool vlan_filtering,struct netlink_ext_ack * extack)1089 static int mxl862xx_port_vlan_filtering(struct dsa_switch *ds, int port,
1090 bool vlan_filtering,
1091 struct netlink_ext_ack *extack)
1092 {
1093 struct mxl862xx_priv *priv = ds->priv;
1094 struct mxl862xx_port *p = &priv->ports[port];
1095 bool old_vlan_filtering = p->vlan_filtering;
1096 bool old_in_use = p->ingress_evlan.in_use;
1097 bool changed = (p->vlan_filtering != vlan_filtering);
1098 int ret;
1099
1100 p->vlan_filtering = vlan_filtering;
1101
1102 if (changed) {
1103 /* When leaving VLAN-aware mode, release the ingress HW
1104 * block. The firmware passes frames through unchanged
1105 * when no ingress EVLAN block is assigned, so the block
1106 * is unnecessary in unaware mode.
1107 */
1108 if (!vlan_filtering)
1109 p->ingress_evlan.in_use = false;
1110
1111 ret = mxl862xx_evlan_program_ingress(priv, port);
1112 if (ret)
1113 goto err_restore;
1114
1115 ret = mxl862xx_evlan_program_egress(priv, port);
1116 if (ret)
1117 goto err_restore;
1118 }
1119
1120 return mxl862xx_set_bridge_port(ds, port);
1121
1122 /* No HW rollback -- restoring SW state is sufficient for a correct retry. */
1123 err_restore:
1124 p->vlan_filtering = old_vlan_filtering;
1125 p->ingress_evlan.in_use = old_in_use;
1126 return ret;
1127 }
1128
mxl862xx_port_vlan_add(struct dsa_switch * ds,int port,const struct switchdev_obj_port_vlan * vlan,struct netlink_ext_ack * extack)1129 static int mxl862xx_port_vlan_add(struct dsa_switch *ds, int port,
1130 const struct switchdev_obj_port_vlan *vlan,
1131 struct netlink_ext_ack *extack)
1132 {
1133 struct mxl862xx_priv *priv = ds->priv;
1134 struct mxl862xx_port *p = &priv->ports[port];
1135 bool untagged = !!(vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED);
1136 u16 vid = vlan->vid;
1137 u16 old_pvid = p->pvid;
1138 bool pvid_changed = false;
1139 int ret;
1140
1141 /* CPU port is VLAN-transparent: the SP tag handles port
1142 * identification and the host-side DSA tagger manages VLAN
1143 * delivery. Egress EVLAN catchalls are set up once in
1144 * setup_cpu_bridge; no per-VID VF/EVLAN programming needed.
1145 */
1146 if (dsa_is_cpu_port(ds, port))
1147 return 0;
1148
1149 /* Update PVID tracking */
1150 if (vlan->flags & BRIDGE_VLAN_INFO_PVID) {
1151 if (p->pvid != vid) {
1152 p->pvid = vid;
1153 pvid_changed = true;
1154 }
1155 } else if (p->pvid == vid) {
1156 p->pvid = 0;
1157 pvid_changed = true;
1158 }
1159
1160 /* Add/update VID in this port's VLAN Filter block.
1161 * VF must be updated before programming egress EVLAN because
1162 * evlan_program_egress walks the VF VID list.
1163 */
1164 ret = mxl862xx_vf_add_vid(priv, &p->vf, vid, untagged);
1165 if (ret)
1166 goto err_pvid;
1167
1168 /* Reprogram ingress finals if PVID changed */
1169 if (pvid_changed) {
1170 ret = mxl862xx_evlan_program_ingress(priv, port);
1171 if (ret)
1172 goto err_rollback;
1173 }
1174
1175 /* Reprogram egress tag-stripping rules (walks VF VID list) */
1176 ret = mxl862xx_evlan_program_egress(priv, port);
1177 if (ret)
1178 goto err_rollback;
1179
1180 /* Apply VLAN block IDs and MAC learning flags to bridge port */
1181 ret = mxl862xx_set_bridge_port(ds, port);
1182 if (ret)
1183 goto err_rollback;
1184
1185 return 0;
1186
1187 err_rollback:
1188 /* Best-effort: undo VF add and restore consistent hardware state.
1189 * A retry of port_vlan_add will converge since vf_add_vid is
1190 * idempotent.
1191 */
1192 p->pvid = old_pvid;
1193 mxl862xx_vf_del_vid(priv, &p->vf, vid);
1194 mxl862xx_evlan_program_ingress(priv, port);
1195 mxl862xx_evlan_program_egress(priv, port);
1196 mxl862xx_set_bridge_port(ds, port);
1197 return ret;
1198 err_pvid:
1199 p->pvid = old_pvid;
1200 return ret;
1201 }
1202
mxl862xx_port_vlan_del(struct dsa_switch * ds,int port,const struct switchdev_obj_port_vlan * vlan)1203 static int mxl862xx_port_vlan_del(struct dsa_switch *ds, int port,
1204 const struct switchdev_obj_port_vlan *vlan)
1205 {
1206 struct mxl862xx_priv *priv = ds->priv;
1207 struct mxl862xx_port *p = &priv->ports[port];
1208 struct mxl862xx_vf_vid *ve;
1209 bool pvid_changed = false;
1210 u16 vid = vlan->vid;
1211 bool old_untagged;
1212 u16 old_pvid;
1213 int ret;
1214
1215 if (dsa_is_cpu_port(ds, port))
1216 return 0;
1217
1218 ve = mxl862xx_vf_find_vid(&p->vf, vid);
1219 if (!ve)
1220 return 0;
1221 old_untagged = ve->untagged;
1222 old_pvid = p->pvid;
1223
1224 /* Clear PVID if we're deleting it */
1225 if (p->pvid == vid) {
1226 p->pvid = 0;
1227 pvid_changed = true;
1228 }
1229
1230 /* Remove VID from this port's VLAN Filter block.
1231 * Must happen before egress reprogram so the VID is no
1232 * longer in the list that evlan_program_egress walks.
1233 */
1234 ret = mxl862xx_vf_del_vid(priv, &p->vf, vid);
1235 if (ret)
1236 goto err_pvid;
1237
1238 /* Reprogram egress tag-stripping rules (VID is now gone) */
1239 ret = mxl862xx_evlan_program_egress(priv, port);
1240 if (ret)
1241 goto err_rollback;
1242
1243 /* If PVID changed, reprogram ingress finals */
1244 if (pvid_changed) {
1245 ret = mxl862xx_evlan_program_ingress(priv, port);
1246 if (ret)
1247 goto err_rollback;
1248 }
1249
1250 ret = mxl862xx_set_bridge_port(ds, port);
1251 if (ret)
1252 goto err_rollback;
1253
1254 return 0;
1255
1256 err_rollback:
1257 /* Best-effort: re-add the VID and restore consistent hardware
1258 * state. A retry of port_vlan_del will converge.
1259 */
1260 p->pvid = old_pvid;
1261 mxl862xx_vf_add_vid(priv, &p->vf, vid, old_untagged);
1262 mxl862xx_evlan_program_egress(priv, port);
1263 mxl862xx_evlan_program_ingress(priv, port);
1264 mxl862xx_set_bridge_port(ds, port);
1265 return ret;
1266 err_pvid:
1267 p->pvid = old_pvid;
1268 return ret;
1269 }
1270
mxl862xx_setup_cpu_bridge(struct dsa_switch * ds,int port)1271 static int mxl862xx_setup_cpu_bridge(struct dsa_switch *ds, int port)
1272 {
1273 struct mxl862xx_priv *priv = ds->priv;
1274 struct mxl862xx_port *p = &priv->ports[port];
1275
1276 p->fid = MXL862XX_DEFAULT_BRIDGE;
1277 p->learning = true;
1278
1279 /* EVLAN is left disabled on CPU ports -- frames pass through
1280 * without EVLAN processing. Only the portmap and bridge
1281 * assignment need to be configured.
1282 */
1283
1284 return mxl862xx_set_bridge_port(ds, port);
1285 }
1286
mxl862xx_port_bridge_join(struct dsa_switch * ds,int port,const struct dsa_bridge bridge,bool * tx_fwd_offload,struct netlink_ext_ack * extack)1287 static int mxl862xx_port_bridge_join(struct dsa_switch *ds, int port,
1288 const struct dsa_bridge bridge,
1289 bool *tx_fwd_offload,
1290 struct netlink_ext_ack *extack)
1291 {
1292 struct mxl862xx_priv *priv = ds->priv;
1293 int ret;
1294
1295 if (!priv->bridges[bridge.num]) {
1296 ret = mxl862xx_allocate_bridge(priv);
1297 if (ret < 0)
1298 return ret;
1299
1300 priv->bridges[bridge.num] = ret;
1301
1302 /* Free bridge here on error, DSA rollback won't. */
1303 ret = mxl862xx_sync_bridge_members(ds, &bridge);
1304 if (ret) {
1305 mxl862xx_free_bridge(ds, &bridge);
1306 return ret;
1307 }
1308
1309 return 0;
1310 }
1311
1312 return mxl862xx_sync_bridge_members(ds, &bridge);
1313 }
1314
mxl862xx_port_bridge_leave(struct dsa_switch * ds,int port,const struct dsa_bridge bridge)1315 static void mxl862xx_port_bridge_leave(struct dsa_switch *ds, int port,
1316 const struct dsa_bridge bridge)
1317 {
1318 struct mxl862xx_priv *priv = ds->priv;
1319 struct mxl862xx_port *p = &priv->ports[port];
1320 int err;
1321
1322 err = mxl862xx_sync_bridge_members(ds, &bridge);
1323 if (err)
1324 dev_err(ds->dev,
1325 "failed to sync bridge members after port %d left: %pe\n",
1326 port, ERR_PTR(err));
1327
1328 /* Revert leaving port, omitted by the sync above, to its
1329 * single-port bridge
1330 */
1331 p->pvid = 0;
1332 p->ingress_evlan.in_use = false;
1333 p->egress_evlan.in_use = false;
1334
1335 err = mxl862xx_set_bridge_port(ds, port);
1336 if (err)
1337 dev_err(ds->dev,
1338 "failed to update bridge port %d state: %pe\n", port,
1339 ERR_PTR(err));
1340
1341 if (!dsa_bridge_ports(ds, bridge.dev))
1342 mxl862xx_free_bridge(ds, &bridge);
1343 }
1344
mxl862xx_port_setup(struct dsa_switch * ds,int port)1345 static int mxl862xx_port_setup(struct dsa_switch *ds, int port)
1346 {
1347 struct mxl862xx_priv *priv = ds->priv;
1348 struct dsa_port *dp = dsa_to_port(ds, port);
1349 bool is_cpu_port = dsa_port_is_cpu(dp);
1350 int ret;
1351
1352 ret = mxl862xx_port_state(ds, port, false);
1353 if (ret)
1354 return ret;
1355
1356 mxl862xx_port_fast_age(ds, port);
1357
1358 if (dsa_port_is_unused(dp))
1359 return 0;
1360
1361 if (dsa_port_is_dsa(dp)) {
1362 dev_err(ds->dev, "port %d: DSA links not supported\n", port);
1363 return -EOPNOTSUPP;
1364 }
1365
1366 ret = mxl862xx_configure_sp_tag_proto(ds, port, is_cpu_port);
1367 if (ret)
1368 return ret;
1369
1370 ret = mxl862xx_configure_ctp_port(ds, port, port,
1371 is_cpu_port ? 32 - port : 1);
1372 if (ret)
1373 return ret;
1374
1375 if (is_cpu_port)
1376 return mxl862xx_setup_cpu_bridge(ds, port);
1377
1378 /* setup single-port bridge for user ports.
1379 * If this fails, the FID is leaked -- but the port then transitions
1380 * to unused, and the FID pool is sized to tolerate this.
1381 */
1382 ret = mxl862xx_allocate_bridge(priv);
1383 if (ret < 0) {
1384 dev_err(ds->dev, "failed to allocate a bridge for port %d\n", port);
1385 return ret;
1386 }
1387 priv->ports[port].fid = ret;
1388 /* Standalone ports should not flood unknown unicast or multicast
1389 * towards the CPU by default; only broadcast is needed initially.
1390 */
1391 ret = mxl862xx_bridge_config_fwd(ds, priv->ports[port].fid,
1392 false, false, true);
1393 if (ret)
1394 return ret;
1395 ret = mxl862xx_set_bridge_port(ds, port);
1396 if (ret)
1397 return ret;
1398
1399 priv->ports[port].ingress_evlan.block_size = priv->evlan_ingress_size;
1400 ret = mxl862xx_evlan_block_alloc(priv, &priv->ports[port].ingress_evlan);
1401 if (ret)
1402 return ret;
1403
1404 priv->ports[port].egress_evlan.block_size = priv->evlan_egress_size;
1405 ret = mxl862xx_evlan_block_alloc(priv, &priv->ports[port].egress_evlan);
1406 if (ret)
1407 return ret;
1408
1409 priv->ports[port].vf.block_size = priv->vf_block_size;
1410 INIT_LIST_HEAD(&priv->ports[port].vf.vids);
1411 ret = mxl862xx_vf_alloc(priv, &priv->ports[port].vf);
1412 if (ret)
1413 return ret;
1414
1415 priv->ports[port].setup_done = true;
1416
1417 return 0;
1418 }
1419
mxl862xx_port_teardown(struct dsa_switch * ds,int port)1420 static void mxl862xx_port_teardown(struct dsa_switch *ds, int port)
1421 {
1422 struct mxl862xx_priv *priv = ds->priv;
1423 struct dsa_port *dp = dsa_to_port(ds, port);
1424
1425 if (dsa_port_is_unused(dp))
1426 return;
1427
1428 /* Prevent deferred host_flood_work from acting on stale state.
1429 * The flag is checked under rtnl_lock() by the worker; since
1430 * teardown also runs under RTNL, this is race-free.
1431 *
1432 * HW EVLAN/VF blocks are not freed here -- the firmware receives
1433 * a full reset on the next probe, which reclaims all resources.
1434 */
1435 priv->ports[port].setup_done = false;
1436 }
1437
mxl862xx_get_fid(struct dsa_switch * ds,struct dsa_db db)1438 static int mxl862xx_get_fid(struct dsa_switch *ds, struct dsa_db db)
1439 {
1440 struct mxl862xx_priv *priv = ds->priv;
1441
1442 switch (db.type) {
1443 case DSA_DB_PORT:
1444 return priv->ports[db.dp->index].fid;
1445
1446 case DSA_DB_BRIDGE:
1447 if (!priv->bridges[db.bridge.num])
1448 return -ENOENT;
1449 return priv->bridges[db.bridge.num];
1450
1451 default:
1452 return -EOPNOTSUPP;
1453 }
1454 }
1455
mxl862xx_port_fdb_add(struct dsa_switch * ds,int port,const unsigned char * addr,u16 vid,struct dsa_db db)1456 static int mxl862xx_port_fdb_add(struct dsa_switch *ds, int port,
1457 const unsigned char *addr, u16 vid, struct dsa_db db)
1458 {
1459 struct mxl862xx_mac_table_add param = {};
1460 int fid = mxl862xx_get_fid(ds, db), ret;
1461 struct mxl862xx_priv *priv = ds->priv;
1462
1463 if (fid < 0)
1464 return fid;
1465
1466 param.port_id = cpu_to_le32(port);
1467 param.static_entry = true;
1468 param.fid = cpu_to_le16(fid);
1469 param.tci = cpu_to_le16(FIELD_PREP(MXL862XX_TCI_VLAN_ID, vid));
1470 ether_addr_copy(param.mac, addr);
1471
1472 ret = MXL862XX_API_WRITE(priv, MXL862XX_MAC_TABLEENTRYADD, param);
1473 if (ret)
1474 dev_err(ds->dev, "failed to add FDB entry on port %d\n", port);
1475
1476 return ret;
1477 }
1478
mxl862xx_port_fdb_del(struct dsa_switch * ds,int port,const unsigned char * addr,u16 vid,const struct dsa_db db)1479 static int mxl862xx_port_fdb_del(struct dsa_switch *ds, int port,
1480 const unsigned char *addr, u16 vid, const struct dsa_db db)
1481 {
1482 struct mxl862xx_mac_table_remove param = {};
1483 int fid = mxl862xx_get_fid(ds, db), ret;
1484 struct mxl862xx_priv *priv = ds->priv;
1485
1486 if (fid < 0)
1487 return fid;
1488
1489 param.fid = cpu_to_le16(fid);
1490 param.tci = cpu_to_le16(FIELD_PREP(MXL862XX_TCI_VLAN_ID, vid));
1491 ether_addr_copy(param.mac, addr);
1492
1493 ret = MXL862XX_API_WRITE(priv, MXL862XX_MAC_TABLEENTRYREMOVE, param);
1494 if (ret)
1495 dev_err(ds->dev, "failed to remove FDB entry on port %d\n", port);
1496
1497 return ret;
1498 }
1499
mxl862xx_port_fdb_dump(struct dsa_switch * ds,int port,dsa_fdb_dump_cb_t * cb,void * data)1500 static int mxl862xx_port_fdb_dump(struct dsa_switch *ds, int port,
1501 dsa_fdb_dump_cb_t *cb, void *data)
1502 {
1503 struct mxl862xx_mac_table_read param = { .initial = 1 };
1504 struct mxl862xx_priv *priv = ds->priv;
1505 u32 entry_port_id;
1506 int ret;
1507
1508 while (true) {
1509 ret = MXL862XX_API_READ(priv, MXL862XX_MAC_TABLEENTRYREAD, param);
1510 if (ret)
1511 return ret;
1512
1513 if (param.last)
1514 break;
1515
1516 entry_port_id = le32_to_cpu(param.port_id);
1517
1518 if (entry_port_id == port) {
1519 ret = cb(param.mac, FIELD_GET(MXL862XX_TCI_VLAN_ID,
1520 le16_to_cpu(param.tci)),
1521 param.static_entry, data);
1522 if (ret)
1523 return ret;
1524 }
1525
1526 memset(¶m, 0, sizeof(param));
1527 }
1528
1529 return 0;
1530 }
1531
mxl862xx_port_mdb_add(struct dsa_switch * ds,int port,const struct switchdev_obj_port_mdb * mdb,const struct dsa_db db)1532 static int mxl862xx_port_mdb_add(struct dsa_switch *ds, int port,
1533 const struct switchdev_obj_port_mdb *mdb,
1534 const struct dsa_db db)
1535 {
1536 struct mxl862xx_mac_table_query qparam = {};
1537 struct mxl862xx_mac_table_add aparam = {};
1538 struct mxl862xx_priv *priv = ds->priv;
1539 int fid, ret;
1540
1541 fid = mxl862xx_get_fid(ds, db);
1542 if (fid < 0)
1543 return fid;
1544
1545 ether_addr_copy(qparam.mac, mdb->addr);
1546 qparam.fid = cpu_to_le16(fid);
1547 qparam.tci = cpu_to_le16(FIELD_PREP(MXL862XX_TCI_VLAN_ID, mdb->vid));
1548
1549 ret = MXL862XX_API_READ(priv, MXL862XX_MAC_TABLEENTRYQUERY, qparam);
1550 if (ret)
1551 return ret;
1552
1553 /* Build the ADD command using portmap mode */
1554 ether_addr_copy(aparam.mac, mdb->addr);
1555 aparam.fid = cpu_to_le16(fid);
1556 aparam.tci = cpu_to_le16(FIELD_PREP(MXL862XX_TCI_VLAN_ID, mdb->vid));
1557 aparam.static_entry = true;
1558 aparam.port_id = cpu_to_le32(MXL862XX_PORTMAP_FLAG);
1559
1560 if (qparam.found)
1561 memcpy(aparam.port_map, qparam.port_map,
1562 sizeof(aparam.port_map));
1563
1564 mxl862xx_fw_portmap_set_bit(aparam.port_map, port);
1565
1566 return MXL862XX_API_WRITE(priv, MXL862XX_MAC_TABLEENTRYADD, aparam);
1567 }
1568
mxl862xx_port_mdb_del(struct dsa_switch * ds,int port,const struct switchdev_obj_port_mdb * mdb,const struct dsa_db db)1569 static int mxl862xx_port_mdb_del(struct dsa_switch *ds, int port,
1570 const struct switchdev_obj_port_mdb *mdb,
1571 const struct dsa_db db)
1572 {
1573 struct mxl862xx_mac_table_remove rparam = {};
1574 struct mxl862xx_mac_table_query qparam = {};
1575 struct mxl862xx_mac_table_add aparam = {};
1576 int fid = mxl862xx_get_fid(ds, db), ret;
1577 struct mxl862xx_priv *priv = ds->priv;
1578
1579 if (fid < 0)
1580 return fid;
1581
1582 qparam.fid = cpu_to_le16(fid);
1583 qparam.tci = cpu_to_le16(FIELD_PREP(MXL862XX_TCI_VLAN_ID, mdb->vid));
1584 ether_addr_copy(qparam.mac, mdb->addr);
1585
1586 ret = MXL862XX_API_READ(priv, MXL862XX_MAC_TABLEENTRYQUERY, qparam);
1587 if (ret)
1588 return ret;
1589
1590 if (!qparam.found)
1591 return 0;
1592
1593 mxl862xx_fw_portmap_clear_bit(qparam.port_map, port);
1594
1595 if (mxl862xx_fw_portmap_is_empty(qparam.port_map)) {
1596 rparam.fid = cpu_to_le16(fid);
1597 rparam.tci = cpu_to_le16(FIELD_PREP(MXL862XX_TCI_VLAN_ID, mdb->vid));
1598 ether_addr_copy(rparam.mac, mdb->addr);
1599 ret = MXL862XX_API_WRITE(priv, MXL862XX_MAC_TABLEENTRYREMOVE, rparam);
1600 } else {
1601 /* Write back with reduced portmap */
1602 aparam.fid = cpu_to_le16(fid);
1603 aparam.tci = cpu_to_le16(FIELD_PREP(MXL862XX_TCI_VLAN_ID, mdb->vid));
1604 ether_addr_copy(aparam.mac, mdb->addr);
1605 aparam.static_entry = true;
1606 aparam.port_id = cpu_to_le32(MXL862XX_PORTMAP_FLAG);
1607 memcpy(aparam.port_map, qparam.port_map, sizeof(aparam.port_map));
1608 ret = MXL862XX_API_WRITE(priv, MXL862XX_MAC_TABLEENTRYADD, aparam);
1609 }
1610
1611 return ret;
1612 }
1613
mxl862xx_set_ageing_time(struct dsa_switch * ds,unsigned int msecs)1614 static int mxl862xx_set_ageing_time(struct dsa_switch *ds, unsigned int msecs)
1615 {
1616 struct mxl862xx_cfg param = {};
1617 int ret;
1618
1619 ret = MXL862XX_API_READ(ds->priv, MXL862XX_COMMON_CFGGET, param);
1620 if (ret) {
1621 dev_err(ds->dev, "failed to read switch config\n");
1622 return ret;
1623 }
1624
1625 param.mac_table_age_timer = cpu_to_le32(MXL862XX_AGETIMER_CUSTOM);
1626 param.age_timer = cpu_to_le32(msecs / 1000);
1627 ret = MXL862XX_API_WRITE(ds->priv, MXL862XX_COMMON_CFGSET, param);
1628 if (ret)
1629 dev_err(ds->dev, "failed to set ageing\n");
1630
1631 return ret;
1632 }
1633
mxl862xx_port_stp_state_set(struct dsa_switch * ds,int port,u8 state)1634 static void mxl862xx_port_stp_state_set(struct dsa_switch *ds, int port,
1635 u8 state)
1636 {
1637 struct mxl862xx_stp_port_cfg param = {
1638 .port_id = cpu_to_le16(port),
1639 };
1640 struct mxl862xx_priv *priv = ds->priv;
1641 int ret;
1642
1643 switch (state) {
1644 case BR_STATE_DISABLED:
1645 param.port_state = cpu_to_le32(MXL862XX_STP_PORT_STATE_DISABLE);
1646 break;
1647 case BR_STATE_BLOCKING:
1648 case BR_STATE_LISTENING:
1649 param.port_state = cpu_to_le32(MXL862XX_STP_PORT_STATE_BLOCKING);
1650 break;
1651 case BR_STATE_LEARNING:
1652 param.port_state = cpu_to_le32(MXL862XX_STP_PORT_STATE_LEARNING);
1653 break;
1654 case BR_STATE_FORWARDING:
1655 param.port_state = cpu_to_le32(MXL862XX_STP_PORT_STATE_FORWARD);
1656 break;
1657 default:
1658 dev_err(ds->dev, "invalid STP state: %d\n", state);
1659 return;
1660 }
1661
1662 ret = MXL862XX_API_WRITE(priv, MXL862XX_STP_PORTCFGSET, param);
1663 if (ret) {
1664 dev_err(ds->dev, "failed to set STP state on port %d\n", port);
1665 return;
1666 }
1667
1668 /* The firmware may re-enable MAC learning as a side-effect of entering
1669 * LEARNING or FORWARDING state (per 802.1D defaults).
1670 * Re-apply the driver's intended learning and metering config so that
1671 * standalone ports keep learning disabled.
1672 */
1673 ret = mxl862xx_set_bridge_port(ds, port);
1674 if (ret)
1675 dev_err(ds->dev, "failed to reapply brport flags on port %d\n",
1676 port);
1677
1678 mxl862xx_port_fast_age(ds, port);
1679 }
1680
1681 /* Deferred work handler for host flood configuration.
1682 *
1683 * port_set_host_flood is called from atomic context (under
1684 * netif_addr_lock), so firmware calls must be deferred. The worker
1685 * acquires rtnl_lock() to serialize with DSA callbacks that access the
1686 * same driver state.
1687 */
mxl862xx_host_flood_work_fn(struct work_struct * work)1688 static void mxl862xx_host_flood_work_fn(struct work_struct *work)
1689 {
1690 struct mxl862xx_port *p = container_of(work, struct mxl862xx_port,
1691 host_flood_work);
1692 struct mxl862xx_priv *priv = p->priv;
1693 struct dsa_switch *ds = priv->ds;
1694
1695 rtnl_lock();
1696
1697 /* Port may have been torn down between scheduling and now. */
1698 if (!p->setup_done) {
1699 rtnl_unlock();
1700 return;
1701 }
1702
1703 /* Always write to the standalone FID. When standalone it takes effect
1704 * immediately; when bridged the port uses the shared bridge FID so the
1705 * write is a no-op for current forwarding, but the state is preserved
1706 * in hardware and is ready once the port returns to standalone.
1707 */
1708 mxl862xx_bridge_config_fwd(ds, p->fid, p->host_flood_uc,
1709 p->host_flood_mc, true);
1710
1711 rtnl_unlock();
1712 }
1713
mxl862xx_port_set_host_flood(struct dsa_switch * ds,int port,bool uc,bool mc)1714 static void mxl862xx_port_set_host_flood(struct dsa_switch *ds, int port,
1715 bool uc, bool mc)
1716 {
1717 struct mxl862xx_priv *priv = ds->priv;
1718 struct mxl862xx_port *p = &priv->ports[port];
1719
1720 p->host_flood_uc = uc;
1721 p->host_flood_mc = mc;
1722 schedule_work(&p->host_flood_work);
1723 }
1724
mxl862xx_port_pre_bridge_flags(struct dsa_switch * ds,int port,const struct switchdev_brport_flags flags,struct netlink_ext_ack * extack)1725 static int mxl862xx_port_pre_bridge_flags(struct dsa_switch *ds, int port,
1726 const struct switchdev_brport_flags flags,
1727 struct netlink_ext_ack *extack)
1728 {
1729 if (flags.mask & ~(BR_FLOOD | BR_MCAST_FLOOD | BR_BCAST_FLOOD |
1730 BR_LEARNING))
1731 return -EINVAL;
1732
1733 return 0;
1734 }
1735
mxl862xx_port_bridge_flags(struct dsa_switch * ds,int port,const struct switchdev_brport_flags flags,struct netlink_ext_ack * extack)1736 static int mxl862xx_port_bridge_flags(struct dsa_switch *ds, int port,
1737 const struct switchdev_brport_flags flags,
1738 struct netlink_ext_ack *extack)
1739 {
1740 struct mxl862xx_priv *priv = ds->priv;
1741 unsigned long old_block = priv->ports[port].flood_block;
1742 unsigned long block = old_block;
1743 int ret;
1744
1745 if (flags.mask & BR_FLOOD) {
1746 if (flags.val & BR_FLOOD)
1747 block &= ~BIT(MXL862XX_BRIDGE_PORT_EGRESS_METER_UNKNOWN_UC);
1748 else
1749 block |= BIT(MXL862XX_BRIDGE_PORT_EGRESS_METER_UNKNOWN_UC);
1750 }
1751
1752 if (flags.mask & BR_MCAST_FLOOD) {
1753 if (flags.val & BR_MCAST_FLOOD) {
1754 block &= ~BIT(MXL862XX_BRIDGE_PORT_EGRESS_METER_UNKNOWN_MC_IP);
1755 block &= ~BIT(MXL862XX_BRIDGE_PORT_EGRESS_METER_UNKNOWN_MC_NON_IP);
1756 } else {
1757 block |= BIT(MXL862XX_BRIDGE_PORT_EGRESS_METER_UNKNOWN_MC_IP);
1758 block |= BIT(MXL862XX_BRIDGE_PORT_EGRESS_METER_UNKNOWN_MC_NON_IP);
1759 }
1760 }
1761
1762 if (flags.mask & BR_BCAST_FLOOD) {
1763 if (flags.val & BR_BCAST_FLOOD)
1764 block &= ~BIT(MXL862XX_BRIDGE_PORT_EGRESS_METER_BROADCAST);
1765 else
1766 block |= BIT(MXL862XX_BRIDGE_PORT_EGRESS_METER_BROADCAST);
1767 }
1768
1769 if (flags.mask & BR_LEARNING)
1770 priv->ports[port].learning = !!(flags.val & BR_LEARNING);
1771
1772 if (block != old_block || (flags.mask & BR_LEARNING)) {
1773 priv->ports[port].flood_block = block;
1774 ret = mxl862xx_set_bridge_port(ds, port);
1775 if (ret)
1776 return ret;
1777 }
1778
1779 return 0;
1780 }
1781
mxl862xx_get_strings(struct dsa_switch * ds,int port,u32 stringset,u8 * data)1782 static void mxl862xx_get_strings(struct dsa_switch *ds, int port,
1783 u32 stringset, u8 *data)
1784 {
1785 int i;
1786
1787 if (stringset != ETH_SS_STATS)
1788 return;
1789
1790 for (i = 0; i < ARRAY_SIZE(mxl862xx_mib); i++)
1791 ethtool_puts(&data, mxl862xx_mib[i].name);
1792 }
1793
mxl862xx_get_sset_count(struct dsa_switch * ds,int port,int sset)1794 static int mxl862xx_get_sset_count(struct dsa_switch *ds, int port, int sset)
1795 {
1796 if (sset != ETH_SS_STATS)
1797 return 0;
1798
1799 return ARRAY_SIZE(mxl862xx_mib);
1800 }
1801
mxl862xx_read_rmon(struct dsa_switch * ds,int port,struct mxl862xx_rmon_port_cnt * cnt)1802 static int mxl862xx_read_rmon(struct dsa_switch *ds, int port,
1803 struct mxl862xx_rmon_port_cnt *cnt)
1804 {
1805 memset(cnt, 0, sizeof(*cnt));
1806 cnt->port_type = cpu_to_le32(MXL862XX_CTP_PORT);
1807 cnt->port_id = cpu_to_le16(port);
1808
1809 return MXL862XX_API_READ(ds->priv, MXL862XX_RMON_PORT_GET, *cnt);
1810 }
1811
mxl862xx_get_ethtool_stats(struct dsa_switch * ds,int port,u64 * data)1812 static void mxl862xx_get_ethtool_stats(struct dsa_switch *ds, int port,
1813 u64 *data)
1814 {
1815 const struct mxl862xx_mib_desc *mib;
1816 struct mxl862xx_rmon_port_cnt cnt;
1817 int ret, i;
1818 void *field;
1819
1820 ret = mxl862xx_read_rmon(ds, port, &cnt);
1821 if (ret) {
1822 dev_err(ds->dev, "failed to read RMON stats on port %d\n", port);
1823 return;
1824 }
1825
1826 for (i = 0; i < ARRAY_SIZE(mxl862xx_mib); i++) {
1827 mib = &mxl862xx_mib[i];
1828 field = (u8 *)&cnt + mib->offset;
1829
1830 if (mib->size == 1)
1831 *data++ = le32_to_cpu(*(__le32 *)field);
1832 else
1833 *data++ = le64_to_cpu(*(__le64 *)field);
1834 }
1835 }
1836
mxl862xx_get_eth_mac_stats(struct dsa_switch * ds,int port,struct ethtool_eth_mac_stats * mac_stats)1837 static void mxl862xx_get_eth_mac_stats(struct dsa_switch *ds, int port,
1838 struct ethtool_eth_mac_stats *mac_stats)
1839 {
1840 struct mxl862xx_rmon_port_cnt cnt;
1841
1842 if (mxl862xx_read_rmon(ds, port, &cnt))
1843 return;
1844
1845 mac_stats->FramesTransmittedOK = le32_to_cpu(cnt.tx_good_pkts);
1846 mac_stats->SingleCollisionFrames = le32_to_cpu(cnt.tx_single_coll_count);
1847 mac_stats->MultipleCollisionFrames = le32_to_cpu(cnt.tx_mult_coll_count);
1848 mac_stats->FramesReceivedOK = le32_to_cpu(cnt.rx_good_pkts);
1849 mac_stats->FrameCheckSequenceErrors = le32_to_cpu(cnt.rx_fcserror_pkts);
1850 mac_stats->AlignmentErrors = le32_to_cpu(cnt.rx_align_error_pkts);
1851 mac_stats->OctetsTransmittedOK = le64_to_cpu(cnt.tx_good_bytes);
1852 mac_stats->LateCollisions = le32_to_cpu(cnt.tx_late_coll_count);
1853 mac_stats->FramesAbortedDueToXSColls = le32_to_cpu(cnt.tx_excess_coll_count);
1854 mac_stats->OctetsReceivedOK = le64_to_cpu(cnt.rx_good_bytes);
1855 mac_stats->MulticastFramesXmittedOK = le32_to_cpu(cnt.tx_multicast_pkts);
1856 mac_stats->BroadcastFramesXmittedOK = le32_to_cpu(cnt.tx_broadcast_pkts);
1857 mac_stats->MulticastFramesReceivedOK = le32_to_cpu(cnt.rx_multicast_pkts);
1858 mac_stats->BroadcastFramesReceivedOK = le32_to_cpu(cnt.rx_broadcast_pkts);
1859 mac_stats->FrameTooLongErrors = le32_to_cpu(cnt.rx_oversize_error_pkts);
1860 }
1861
mxl862xx_get_eth_ctrl_stats(struct dsa_switch * ds,int port,struct ethtool_eth_ctrl_stats * ctrl_stats)1862 static void mxl862xx_get_eth_ctrl_stats(struct dsa_switch *ds, int port,
1863 struct ethtool_eth_ctrl_stats *ctrl_stats)
1864 {
1865 struct mxl862xx_rmon_port_cnt cnt;
1866
1867 if (mxl862xx_read_rmon(ds, port, &cnt))
1868 return;
1869
1870 ctrl_stats->MACControlFramesTransmitted = le32_to_cpu(cnt.tx_pause_count);
1871 ctrl_stats->MACControlFramesReceived = le32_to_cpu(cnt.rx_good_pause_pkts);
1872 }
1873
mxl862xx_get_pause_stats(struct dsa_switch * ds,int port,struct ethtool_pause_stats * pause_stats)1874 static void mxl862xx_get_pause_stats(struct dsa_switch *ds, int port,
1875 struct ethtool_pause_stats *pause_stats)
1876 {
1877 struct mxl862xx_rmon_port_cnt cnt;
1878
1879 if (mxl862xx_read_rmon(ds, port, &cnt))
1880 return;
1881
1882 pause_stats->tx_pause_frames = le32_to_cpu(cnt.tx_pause_count);
1883 pause_stats->rx_pause_frames = le32_to_cpu(cnt.rx_good_pause_pkts);
1884 }
1885
mxl862xx_get_rmon_stats(struct dsa_switch * ds,int port,struct ethtool_rmon_stats * rmon_stats,const struct ethtool_rmon_hist_range ** ranges)1886 static void mxl862xx_get_rmon_stats(struct dsa_switch *ds, int port,
1887 struct ethtool_rmon_stats *rmon_stats,
1888 const struct ethtool_rmon_hist_range **ranges)
1889 {
1890 struct mxl862xx_rmon_port_cnt cnt;
1891
1892 if (mxl862xx_read_rmon(ds, port, &cnt))
1893 return;
1894
1895 rmon_stats->undersize_pkts = le32_to_cpu(cnt.rx_under_size_good_pkts);
1896 rmon_stats->oversize_pkts = le32_to_cpu(cnt.rx_oversize_good_pkts);
1897 rmon_stats->fragments = le32_to_cpu(cnt.rx_under_size_error_pkts);
1898 rmon_stats->jabbers = le32_to_cpu(cnt.rx_oversize_error_pkts);
1899
1900 rmon_stats->hist[0] = le32_to_cpu(cnt.rx64byte_pkts);
1901 rmon_stats->hist[1] = le32_to_cpu(cnt.rx127byte_pkts);
1902 rmon_stats->hist[2] = le32_to_cpu(cnt.rx255byte_pkts);
1903 rmon_stats->hist[3] = le32_to_cpu(cnt.rx511byte_pkts);
1904 rmon_stats->hist[4] = le32_to_cpu(cnt.rx1023byte_pkts);
1905 rmon_stats->hist[5] = le32_to_cpu(cnt.rx_max_byte_pkts);
1906
1907 rmon_stats->hist_tx[0] = le32_to_cpu(cnt.tx64byte_pkts);
1908 rmon_stats->hist_tx[1] = le32_to_cpu(cnt.tx127byte_pkts);
1909 rmon_stats->hist_tx[2] = le32_to_cpu(cnt.tx255byte_pkts);
1910 rmon_stats->hist_tx[3] = le32_to_cpu(cnt.tx511byte_pkts);
1911 rmon_stats->hist_tx[4] = le32_to_cpu(cnt.tx1023byte_pkts);
1912 rmon_stats->hist_tx[5] = le32_to_cpu(cnt.tx_max_byte_pkts);
1913
1914 *ranges = mxl862xx_rmon_ranges;
1915 }
1916
1917 /* Compute the delta between two 32-bit free-running counter snapshots,
1918 * handling a single wrap-around correctly via unsigned subtraction.
1919 */
mxl862xx_delta32(u32 cur,u32 prev)1920 static u64 mxl862xx_delta32(u32 cur, u32 prev)
1921 {
1922 return (u32)(cur - prev);
1923 }
1924
1925 /**
1926 * mxl862xx_stats_poll - Read RMON counters and accumulate into 64-bit stats
1927 * @ds: DSA switch
1928 * @port: port index
1929 *
1930 * The firmware RMON counters are free-running 32-bit values (64-bit for
1931 * byte counters). This function reads the hardware via MDIO (may sleep),
1932 * computes deltas from the previous snapshot, and accumulates them into
1933 * 64-bit per-port stats under a spinlock.
1934 *
1935 * Called only from the stats polling workqueue -- serialized by the
1936 * single-threaded delayed_work, so no MDIO locking is needed here.
1937 */
mxl862xx_stats_poll(struct dsa_switch * ds,int port)1938 static void mxl862xx_stats_poll(struct dsa_switch *ds, int port)
1939 {
1940 struct mxl862xx_priv *priv = ds->priv;
1941 struct mxl862xx_port_stats *s = &priv->ports[port].stats;
1942 u32 rx_fcserr, rx_under, rx_over, rx_align, tx_drop;
1943 u32 rx_drop, rx_evlan, mtu_exc, tx_acm;
1944 struct mxl862xx_rmon_port_cnt cnt;
1945 u64 rx_bytes, tx_bytes;
1946 u32 rx_mcast, tx_coll;
1947 u32 rx_pkts, tx_pkts;
1948
1949 /* MDIO read -- may sleep, done outside the spinlock. */
1950 if (mxl862xx_read_rmon(ds, port, &cnt))
1951 return;
1952
1953 rx_pkts = le32_to_cpu(cnt.rx_good_pkts);
1954 tx_pkts = le32_to_cpu(cnt.tx_good_pkts);
1955 rx_bytes = le64_to_cpu(cnt.rx_good_bytes);
1956 tx_bytes = le64_to_cpu(cnt.tx_good_bytes);
1957 rx_fcserr = le32_to_cpu(cnt.rx_fcserror_pkts);
1958 rx_under = le32_to_cpu(cnt.rx_under_size_error_pkts);
1959 rx_over = le32_to_cpu(cnt.rx_oversize_error_pkts);
1960 rx_align = le32_to_cpu(cnt.rx_align_error_pkts);
1961 tx_drop = le32_to_cpu(cnt.tx_dropped_pkts);
1962 rx_drop = le32_to_cpu(cnt.rx_dropped_pkts);
1963 rx_evlan = le32_to_cpu(cnt.rx_extended_vlan_discard_pkts);
1964 mtu_exc = le32_to_cpu(cnt.mtu_exceed_discard_pkts);
1965 tx_acm = le32_to_cpu(cnt.tx_acm_dropped_pkts);
1966 rx_mcast = le32_to_cpu(cnt.rx_multicast_pkts);
1967 tx_coll = le32_to_cpu(cnt.tx_coll_count);
1968
1969 /* Accumulate deltas under spinlock -- .get_stats64 reads these. */
1970 spin_lock_bh(&priv->ports[port].stats_lock);
1971
1972 s->rx_packets += mxl862xx_delta32(rx_pkts, s->prev_rx_good_pkts);
1973 s->tx_packets += mxl862xx_delta32(tx_pkts, s->prev_tx_good_pkts);
1974 s->rx_bytes += rx_bytes - s->prev_rx_good_bytes;
1975 s->tx_bytes += tx_bytes - s->prev_tx_good_bytes;
1976
1977 s->rx_errors +=
1978 mxl862xx_delta32(rx_fcserr, s->prev_rx_fcserror_pkts) +
1979 mxl862xx_delta32(rx_under, s->prev_rx_under_size_error_pkts) +
1980 mxl862xx_delta32(rx_over, s->prev_rx_oversize_error_pkts) +
1981 mxl862xx_delta32(rx_align, s->prev_rx_align_error_pkts);
1982 s->tx_errors +=
1983 mxl862xx_delta32(tx_drop, s->prev_tx_dropped_pkts);
1984
1985 s->rx_dropped +=
1986 mxl862xx_delta32(rx_drop, s->prev_rx_dropped_pkts) +
1987 mxl862xx_delta32(rx_evlan, s->prev_rx_evlan_discard_pkts) +
1988 mxl862xx_delta32(mtu_exc, s->prev_mtu_exceed_discard_pkts);
1989 s->tx_dropped +=
1990 mxl862xx_delta32(tx_drop, s->prev_tx_dropped_pkts) +
1991 mxl862xx_delta32(tx_acm, s->prev_tx_acm_dropped_pkts);
1992
1993 s->multicast += mxl862xx_delta32(rx_mcast, s->prev_rx_multicast_pkts);
1994 s->collisions += mxl862xx_delta32(tx_coll, s->prev_tx_coll_count);
1995
1996 s->rx_length_errors +=
1997 mxl862xx_delta32(rx_under, s->prev_rx_under_size_error_pkts) +
1998 mxl862xx_delta32(rx_over, s->prev_rx_oversize_error_pkts);
1999 s->rx_crc_errors +=
2000 mxl862xx_delta32(rx_fcserr, s->prev_rx_fcserror_pkts);
2001 s->rx_frame_errors +=
2002 mxl862xx_delta32(rx_align, s->prev_rx_align_error_pkts);
2003
2004 s->prev_rx_good_pkts = rx_pkts;
2005 s->prev_tx_good_pkts = tx_pkts;
2006 s->prev_rx_good_bytes = rx_bytes;
2007 s->prev_tx_good_bytes = tx_bytes;
2008 s->prev_rx_fcserror_pkts = rx_fcserr;
2009 s->prev_rx_under_size_error_pkts = rx_under;
2010 s->prev_rx_oversize_error_pkts = rx_over;
2011 s->prev_rx_align_error_pkts = rx_align;
2012 s->prev_tx_dropped_pkts = tx_drop;
2013 s->prev_rx_dropped_pkts = rx_drop;
2014 s->prev_rx_evlan_discard_pkts = rx_evlan;
2015 s->prev_mtu_exceed_discard_pkts = mtu_exc;
2016 s->prev_tx_acm_dropped_pkts = tx_acm;
2017 s->prev_rx_multicast_pkts = rx_mcast;
2018 s->prev_tx_coll_count = tx_coll;
2019
2020 spin_unlock_bh(&priv->ports[port].stats_lock);
2021 }
2022
mxl862xx_stats_work_fn(struct work_struct * work)2023 static void mxl862xx_stats_work_fn(struct work_struct *work)
2024 {
2025 struct mxl862xx_priv *priv =
2026 container_of(work, struct mxl862xx_priv, stats_work.work);
2027 struct dsa_switch *ds = priv->ds;
2028 struct dsa_port *dp;
2029
2030 dsa_switch_for_each_available_port(dp, ds)
2031 mxl862xx_stats_poll(ds, dp->index);
2032
2033 if (!test_bit(MXL862XX_FLAG_WORK_STOPPED, &priv->flags))
2034 schedule_delayed_work(&priv->stats_work,
2035 MXL862XX_STATS_POLL_INTERVAL);
2036 }
2037
mxl862xx_get_stats64(struct dsa_switch * ds,int port,struct rtnl_link_stats64 * s)2038 static void mxl862xx_get_stats64(struct dsa_switch *ds, int port,
2039 struct rtnl_link_stats64 *s)
2040 {
2041 struct mxl862xx_priv *priv = ds->priv;
2042 struct mxl862xx_port_stats *ps = &priv->ports[port].stats;
2043
2044 spin_lock_bh(&priv->ports[port].stats_lock);
2045
2046 s->rx_packets = ps->rx_packets;
2047 s->tx_packets = ps->tx_packets;
2048 s->rx_bytes = ps->rx_bytes;
2049 s->tx_bytes = ps->tx_bytes;
2050 s->rx_errors = ps->rx_errors;
2051 s->tx_errors = ps->tx_errors;
2052 s->rx_dropped = ps->rx_dropped;
2053 s->tx_dropped = ps->tx_dropped;
2054 s->multicast = ps->multicast;
2055 s->collisions = ps->collisions;
2056 s->rx_length_errors = ps->rx_length_errors;
2057 s->rx_crc_errors = ps->rx_crc_errors;
2058 s->rx_frame_errors = ps->rx_frame_errors;
2059
2060 spin_unlock_bh(&priv->ports[port].stats_lock);
2061
2062 /* Trigger a fresh poll so the next read sees up-to-date counters. */
2063 if (!test_bit(MXL862XX_FLAG_WORK_STOPPED, &priv->flags))
2064 schedule_delayed_work(&priv->stats_work, 0);
2065 }
2066
2067 static const struct dsa_switch_ops mxl862xx_switch_ops = {
2068 .get_tag_protocol = mxl862xx_get_tag_protocol,
2069 .setup = mxl862xx_setup,
2070 .teardown = mxl862xx_teardown,
2071 .port_setup = mxl862xx_port_setup,
2072 .port_teardown = mxl862xx_port_teardown,
2073 .phylink_get_caps = mxl862xx_phylink_get_caps,
2074 .port_enable = mxl862xx_port_enable,
2075 .port_disable = mxl862xx_port_disable,
2076 .port_fast_age = mxl862xx_port_fast_age,
2077 .set_ageing_time = mxl862xx_set_ageing_time,
2078 .port_bridge_join = mxl862xx_port_bridge_join,
2079 .port_bridge_leave = mxl862xx_port_bridge_leave,
2080 .port_pre_bridge_flags = mxl862xx_port_pre_bridge_flags,
2081 .port_bridge_flags = mxl862xx_port_bridge_flags,
2082 .port_stp_state_set = mxl862xx_port_stp_state_set,
2083 .port_set_host_flood = mxl862xx_port_set_host_flood,
2084 .port_fdb_add = mxl862xx_port_fdb_add,
2085 .port_fdb_del = mxl862xx_port_fdb_del,
2086 .port_fdb_dump = mxl862xx_port_fdb_dump,
2087 .port_mdb_add = mxl862xx_port_mdb_add,
2088 .port_mdb_del = mxl862xx_port_mdb_del,
2089 .port_vlan_filtering = mxl862xx_port_vlan_filtering,
2090 .port_vlan_add = mxl862xx_port_vlan_add,
2091 .port_vlan_del = mxl862xx_port_vlan_del,
2092 .get_strings = mxl862xx_get_strings,
2093 .get_sset_count = mxl862xx_get_sset_count,
2094 .get_ethtool_stats = mxl862xx_get_ethtool_stats,
2095 .get_eth_mac_stats = mxl862xx_get_eth_mac_stats,
2096 .get_eth_ctrl_stats = mxl862xx_get_eth_ctrl_stats,
2097 .get_pause_stats = mxl862xx_get_pause_stats,
2098 .get_rmon_stats = mxl862xx_get_rmon_stats,
2099 .get_stats64 = mxl862xx_get_stats64,
2100 };
2101
mxl862xx_probe(struct mdio_device * mdiodev)2102 static int mxl862xx_probe(struct mdio_device *mdiodev)
2103 {
2104 struct device *dev = &mdiodev->dev;
2105 struct mxl862xx_priv *priv;
2106 struct dsa_switch *ds;
2107 int err, i;
2108
2109 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
2110 if (!priv)
2111 return -ENOMEM;
2112
2113 priv->mdiodev = mdiodev;
2114
2115 ds = devm_kzalloc(dev, sizeof(*ds), GFP_KERNEL);
2116 if (!ds)
2117 return -ENOMEM;
2118
2119 priv->ds = ds;
2120 ds->dev = dev;
2121 ds->priv = priv;
2122 ds->ops = &mxl862xx_switch_ops;
2123 ds->phylink_mac_ops = &mxl862xx_phylink_mac_ops;
2124 ds->num_ports = MXL862XX_MAX_PORTS;
2125 ds->assisted_learning_on_cpu_port = true;
2126 ds->fdb_isolation = true;
2127 ds->max_num_bridges = MXL862XX_MAX_BRIDGES;
2128
2129 mxl862xx_host_init(priv);
2130
2131 for (i = 0; i < MXL862XX_MAX_PORTS; i++) {
2132 priv->ports[i].priv = priv;
2133 INIT_WORK(&priv->ports[i].host_flood_work,
2134 mxl862xx_host_flood_work_fn);
2135 spin_lock_init(&priv->ports[i].stats_lock);
2136 }
2137
2138 INIT_DELAYED_WORK(&priv->stats_work, mxl862xx_stats_work_fn);
2139
2140 dev_set_drvdata(dev, ds);
2141
2142 err = dsa_register_switch(ds);
2143 if (err) {
2144 set_bit(MXL862XX_FLAG_WORK_STOPPED, &priv->flags);
2145 mxl862xx_host_shutdown(priv);
2146 for (i = 0; i < MXL862XX_MAX_PORTS; i++)
2147 cancel_work_sync(&priv->ports[i].host_flood_work);
2148 }
2149
2150 return err;
2151 }
2152
mxl862xx_remove(struct mdio_device * mdiodev)2153 static void mxl862xx_remove(struct mdio_device *mdiodev)
2154 {
2155 struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev);
2156 struct mxl862xx_priv *priv;
2157 int i;
2158
2159 if (!ds)
2160 return;
2161
2162 priv = ds->priv;
2163
2164 set_bit(MXL862XX_FLAG_WORK_STOPPED, &priv->flags);
2165
2166 dsa_unregister_switch(ds);
2167
2168 mxl862xx_host_shutdown(priv);
2169
2170 /* Cancel any pending host flood work. dsa_unregister_switch()
2171 * has already called port_teardown (which sets setup_done=false),
2172 * but a worker could still be blocked on rtnl_lock(). Since we
2173 * are now outside RTNL, cancel_work_sync() will not deadlock.
2174 */
2175 for (i = 0; i < MXL862XX_MAX_PORTS; i++)
2176 cancel_work_sync(&priv->ports[i].host_flood_work);
2177 }
2178
mxl862xx_shutdown(struct mdio_device * mdiodev)2179 static void mxl862xx_shutdown(struct mdio_device *mdiodev)
2180 {
2181 struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev);
2182 struct mxl862xx_priv *priv;
2183 int i;
2184
2185 if (!ds)
2186 return;
2187
2188 priv = ds->priv;
2189
2190 dsa_switch_shutdown(ds);
2191
2192 set_bit(MXL862XX_FLAG_WORK_STOPPED, &priv->flags);
2193 disable_delayed_work_sync(&priv->stats_work);
2194
2195 mxl862xx_host_shutdown(priv);
2196
2197 for (i = 0; i < MXL862XX_MAX_PORTS; i++)
2198 cancel_work_sync(&priv->ports[i].host_flood_work);
2199
2200 dev_set_drvdata(&mdiodev->dev, NULL);
2201 }
2202
2203 static const struct of_device_id mxl862xx_of_match[] = {
2204 { .compatible = "maxlinear,mxl86282" },
2205 { .compatible = "maxlinear,mxl86252" },
2206 { /* sentinel */ }
2207 };
2208 MODULE_DEVICE_TABLE(of, mxl862xx_of_match);
2209
2210 static struct mdio_driver mxl862xx_driver = {
2211 .probe = mxl862xx_probe,
2212 .remove = mxl862xx_remove,
2213 .shutdown = mxl862xx_shutdown,
2214 .mdiodrv.driver = {
2215 .name = "mxl862xx",
2216 .of_match_table = mxl862xx_of_match,
2217 },
2218 };
2219
2220 mdio_module_driver(mxl862xx_driver);
2221
2222 MODULE_DESCRIPTION("Driver for MaxLinear MxL862xx switch family");
2223 MODULE_LICENSE("GPL");
2224