Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (C) 2020 NovaTech LLC
0004  * George McCollister <george.mccollister@gmail.com>
0005  */
0006 
0007 #include <net/dsa.h>
0008 #include <linux/etherdevice.h>
0009 #include <linux/if_bridge.h>
0010 #include <linux/of_device.h>
0011 #include <linux/netdev_features.h>
0012 #include <linux/if_hsr.h>
0013 #include "xrs700x.h"
0014 #include "xrs700x_reg.h"
0015 
0016 #define XRS700X_MIB_INTERVAL msecs_to_jiffies(3000)
0017 
0018 #define XRS7000X_SUPPORTED_HSR_FEATURES \
0019     (NETIF_F_HW_HSR_TAG_INS | NETIF_F_HW_HSR_TAG_RM | \
0020      NETIF_F_HW_HSR_FWD | NETIF_F_HW_HSR_DUP)
0021 
0022 #define XRS7003E_ID 0x100
0023 #define XRS7003F_ID 0x101
0024 #define XRS7004E_ID 0x200
0025 #define XRS7004F_ID 0x201
0026 
0027 const struct xrs700x_info xrs7003e_info = {XRS7003E_ID, "XRS7003E", 3};
0028 EXPORT_SYMBOL(xrs7003e_info);
0029 
0030 const struct xrs700x_info xrs7003f_info = {XRS7003F_ID, "XRS7003F", 3};
0031 EXPORT_SYMBOL(xrs7003f_info);
0032 
0033 const struct xrs700x_info xrs7004e_info = {XRS7004E_ID, "XRS7004E", 4};
0034 EXPORT_SYMBOL(xrs7004e_info);
0035 
0036 const struct xrs700x_info xrs7004f_info = {XRS7004F_ID, "XRS7004F", 4};
0037 EXPORT_SYMBOL(xrs7004f_info);
0038 
0039 struct xrs700x_regfield {
0040     struct reg_field rf;
0041     struct regmap_field **rmf;
0042 };
0043 
0044 struct xrs700x_mib {
0045     unsigned int offset;
0046     const char *name;
0047     int stats64_offset;
0048 };
0049 
0050 #define XRS700X_MIB_ETHTOOL_ONLY(o, n) {o, n, -1}
0051 #define XRS700X_MIB(o, n, m) {o, n, offsetof(struct rtnl_link_stats64, m)}
0052 
0053 static const struct xrs700x_mib xrs700x_mibs[] = {
0054     XRS700X_MIB(XRS_RX_GOOD_OCTETS_L, "rx_good_octets", rx_bytes),
0055     XRS700X_MIB_ETHTOOL_ONLY(XRS_RX_BAD_OCTETS_L, "rx_bad_octets"),
0056     XRS700X_MIB(XRS_RX_UNICAST_L, "rx_unicast", rx_packets),
0057     XRS700X_MIB(XRS_RX_BROADCAST_L, "rx_broadcast", rx_packets),
0058     XRS700X_MIB(XRS_RX_MULTICAST_L, "rx_multicast", multicast),
0059     XRS700X_MIB(XRS_RX_UNDERSIZE_L, "rx_undersize", rx_length_errors),
0060     XRS700X_MIB(XRS_RX_FRAGMENTS_L, "rx_fragments", rx_length_errors),
0061     XRS700X_MIB(XRS_RX_OVERSIZE_L, "rx_oversize", rx_length_errors),
0062     XRS700X_MIB(XRS_RX_JABBER_L, "rx_jabber", rx_length_errors),
0063     XRS700X_MIB(XRS_RX_ERR_L, "rx_err", rx_errors),
0064     XRS700X_MIB(XRS_RX_CRC_L, "rx_crc", rx_crc_errors),
0065     XRS700X_MIB_ETHTOOL_ONLY(XRS_RX_64_L, "rx_64"),
0066     XRS700X_MIB_ETHTOOL_ONLY(XRS_RX_65_127_L, "rx_65_127"),
0067     XRS700X_MIB_ETHTOOL_ONLY(XRS_RX_128_255_L, "rx_128_255"),
0068     XRS700X_MIB_ETHTOOL_ONLY(XRS_RX_256_511_L, "rx_256_511"),
0069     XRS700X_MIB_ETHTOOL_ONLY(XRS_RX_512_1023_L, "rx_512_1023"),
0070     XRS700X_MIB_ETHTOOL_ONLY(XRS_RX_1024_1536_L, "rx_1024_1536"),
0071     XRS700X_MIB_ETHTOOL_ONLY(XRS_RX_HSR_PRP_L, "rx_hsr_prp"),
0072     XRS700X_MIB_ETHTOOL_ONLY(XRS_RX_WRONGLAN_L, "rx_wronglan"),
0073     XRS700X_MIB_ETHTOOL_ONLY(XRS_RX_DUPLICATE_L, "rx_duplicate"),
0074     XRS700X_MIB(XRS_TX_OCTETS_L, "tx_octets", tx_bytes),
0075     XRS700X_MIB(XRS_TX_UNICAST_L, "tx_unicast", tx_packets),
0076     XRS700X_MIB(XRS_TX_BROADCAST_L, "tx_broadcast", tx_packets),
0077     XRS700X_MIB(XRS_TX_MULTICAST_L, "tx_multicast", tx_packets),
0078     XRS700X_MIB_ETHTOOL_ONLY(XRS_TX_HSR_PRP_L, "tx_hsr_prp"),
0079     XRS700X_MIB(XRS_PRIQ_DROP_L, "priq_drop", tx_dropped),
0080     XRS700X_MIB(XRS_EARLY_DROP_L, "early_drop", tx_dropped),
0081 };
0082 
0083 static const u8 eth_hsrsup_addr[ETH_ALEN] = {
0084     0x01, 0x15, 0x4e, 0x00, 0x01, 0x00};
0085 
0086 static void xrs700x_get_strings(struct dsa_switch *ds, int port,
0087                 u32 stringset, u8 *data)
0088 {
0089     int i;
0090 
0091     if (stringset != ETH_SS_STATS)
0092         return;
0093 
0094     for (i = 0; i < ARRAY_SIZE(xrs700x_mibs); i++) {
0095         strscpy(data, xrs700x_mibs[i].name, ETH_GSTRING_LEN);
0096         data += ETH_GSTRING_LEN;
0097     }
0098 }
0099 
0100 static int xrs700x_get_sset_count(struct dsa_switch *ds, int port, int sset)
0101 {
0102     if (sset != ETH_SS_STATS)
0103         return -EOPNOTSUPP;
0104 
0105     return ARRAY_SIZE(xrs700x_mibs);
0106 }
0107 
0108 static void xrs700x_read_port_counters(struct xrs700x *priv, int port)
0109 {
0110     struct xrs700x_port *p = &priv->ports[port];
0111     struct rtnl_link_stats64 stats;
0112     unsigned long flags;
0113     int i;
0114 
0115     memset(&stats, 0, sizeof(stats));
0116 
0117     mutex_lock(&p->mib_mutex);
0118 
0119     /* Capture counter values */
0120     regmap_write(priv->regmap, XRS_CNT_CTRL(port), 1);
0121 
0122     for (i = 0; i < ARRAY_SIZE(xrs700x_mibs); i++) {
0123         unsigned int high = 0, low = 0, reg;
0124 
0125         reg = xrs700x_mibs[i].offset + XRS_PORT_OFFSET * port;
0126         regmap_read(priv->regmap, reg, &low);
0127         regmap_read(priv->regmap, reg + 2, &high);
0128 
0129         p->mib_data[i] += (high << 16) | low;
0130 
0131         if (xrs700x_mibs[i].stats64_offset >= 0) {
0132             u8 *s = (u8 *)&stats + xrs700x_mibs[i].stats64_offset;
0133             *(u64 *)s += p->mib_data[i];
0134         }
0135     }
0136 
0137     /* multicast must be added to rx_packets (which already includes
0138      * unicast and broadcast)
0139      */
0140     stats.rx_packets += stats.multicast;
0141 
0142     flags = u64_stats_update_begin_irqsave(&p->syncp);
0143     p->stats64 = stats;
0144     u64_stats_update_end_irqrestore(&p->syncp, flags);
0145 
0146     mutex_unlock(&p->mib_mutex);
0147 }
0148 
0149 static void xrs700x_mib_work(struct work_struct *work)
0150 {
0151     struct xrs700x *priv = container_of(work, struct xrs700x,
0152                         mib_work.work);
0153     int i;
0154 
0155     for (i = 0; i < priv->ds->num_ports; i++)
0156         xrs700x_read_port_counters(priv, i);
0157 
0158     schedule_delayed_work(&priv->mib_work, XRS700X_MIB_INTERVAL);
0159 }
0160 
0161 static void xrs700x_get_ethtool_stats(struct dsa_switch *ds, int port,
0162                       u64 *data)
0163 {
0164     struct xrs700x *priv = ds->priv;
0165     struct xrs700x_port *p = &priv->ports[port];
0166 
0167     xrs700x_read_port_counters(priv, port);
0168 
0169     mutex_lock(&p->mib_mutex);
0170     memcpy(data, p->mib_data, sizeof(*data) * ARRAY_SIZE(xrs700x_mibs));
0171     mutex_unlock(&p->mib_mutex);
0172 }
0173 
0174 static void xrs700x_get_stats64(struct dsa_switch *ds, int port,
0175                 struct rtnl_link_stats64 *s)
0176 {
0177     struct xrs700x *priv = ds->priv;
0178     struct xrs700x_port *p = &priv->ports[port];
0179     unsigned int start;
0180 
0181     do {
0182         start = u64_stats_fetch_begin(&p->syncp);
0183         *s = p->stats64;
0184     } while (u64_stats_fetch_retry(&p->syncp, start));
0185 }
0186 
0187 static int xrs700x_setup_regmap_range(struct xrs700x *priv)
0188 {
0189     struct xrs700x_regfield regfields[] = {
0190         {
0191             .rf = REG_FIELD_ID(XRS_PORT_STATE(0), 0, 1,
0192                        priv->ds->num_ports,
0193                        XRS_PORT_OFFSET),
0194             .rmf = &priv->ps_forward
0195         },
0196         {
0197             .rf = REG_FIELD_ID(XRS_PORT_STATE(0), 2, 3,
0198                        priv->ds->num_ports,
0199                        XRS_PORT_OFFSET),
0200             .rmf = &priv->ps_management
0201         },
0202         {
0203             .rf = REG_FIELD_ID(XRS_PORT_STATE(0), 4, 9,
0204                        priv->ds->num_ports,
0205                        XRS_PORT_OFFSET),
0206             .rmf = &priv->ps_sel_speed
0207         },
0208         {
0209             .rf = REG_FIELD_ID(XRS_PORT_STATE(0), 10, 11,
0210                        priv->ds->num_ports,
0211                        XRS_PORT_OFFSET),
0212             .rmf = &priv->ps_cur_speed
0213         }
0214     };
0215     int i = 0;
0216 
0217     for (; i < ARRAY_SIZE(regfields); i++) {
0218         *regfields[i].rmf = devm_regmap_field_alloc(priv->dev,
0219                                 priv->regmap,
0220                                 regfields[i].rf);
0221         if (IS_ERR(*regfields[i].rmf))
0222             return PTR_ERR(*regfields[i].rmf);
0223     }
0224 
0225     return 0;
0226 }
0227 
0228 static enum dsa_tag_protocol xrs700x_get_tag_protocol(struct dsa_switch *ds,
0229                               int port,
0230                               enum dsa_tag_protocol m)
0231 {
0232     return DSA_TAG_PROTO_XRS700X;
0233 }
0234 
0235 static int xrs700x_reset(struct dsa_switch *ds)
0236 {
0237     struct xrs700x *priv = ds->priv;
0238     unsigned int val;
0239     int ret;
0240 
0241     ret = regmap_write(priv->regmap, XRS_GENERAL, XRS_GENERAL_RESET);
0242     if (ret)
0243         goto error;
0244 
0245     ret = regmap_read_poll_timeout(priv->regmap, XRS_GENERAL,
0246                        val, !(val & XRS_GENERAL_RESET),
0247                        10, 1000);
0248 error:
0249     if (ret) {
0250         dev_err_ratelimited(priv->dev, "error resetting switch: %d\n",
0251                     ret);
0252     }
0253 
0254     return ret;
0255 }
0256 
0257 static void xrs700x_port_stp_state_set(struct dsa_switch *ds, int port,
0258                        u8 state)
0259 {
0260     struct xrs700x *priv = ds->priv;
0261     unsigned int bpdus = 1;
0262     unsigned int val;
0263 
0264     switch (state) {
0265     case BR_STATE_DISABLED:
0266         bpdus = 0;
0267         fallthrough;
0268     case BR_STATE_BLOCKING:
0269     case BR_STATE_LISTENING:
0270         val = XRS_PORT_DISABLED;
0271         break;
0272     case BR_STATE_LEARNING:
0273         val = XRS_PORT_LEARNING;
0274         break;
0275     case BR_STATE_FORWARDING:
0276         val = XRS_PORT_FORWARDING;
0277         break;
0278     default:
0279         dev_err(ds->dev, "invalid STP state: %d\n", state);
0280         return;
0281     }
0282 
0283     regmap_fields_write(priv->ps_forward, port, val);
0284 
0285     /* Enable/disable inbound policy added by xrs700x_port_add_bpdu_ipf()
0286      * which allows BPDU forwarding to the CPU port when the front facing
0287      * port is in disabled/learning state.
0288      */
0289     regmap_update_bits(priv->regmap, XRS_ETH_ADDR_CFG(port, 0), 1, bpdus);
0290 
0291     dev_dbg_ratelimited(priv->dev, "%s - port: %d, state: %u, val: 0x%x\n",
0292                 __func__, port, state, val);
0293 }
0294 
0295 /* Add an inbound policy filter which matches the BPDU destination MAC
0296  * and forwards to the CPU port. Leave the policy disabled, it will be
0297  * enabled as needed.
0298  */
0299 static int xrs700x_port_add_bpdu_ipf(struct dsa_switch *ds, int port)
0300 {
0301     struct xrs700x *priv = ds->priv;
0302     unsigned int val = 0;
0303     int i = 0;
0304     int ret;
0305 
0306     /* Compare all 48 bits of the destination MAC address. */
0307     ret = regmap_write(priv->regmap, XRS_ETH_ADDR_CFG(port, 0), 48 << 2);
0308     if (ret)
0309         return ret;
0310 
0311     /* match BPDU destination 01:80:c2:00:00:00 */
0312     for (i = 0; i < sizeof(eth_stp_addr); i += 2) {
0313         ret = regmap_write(priv->regmap, XRS_ETH_ADDR_0(port, 0) + i,
0314                    eth_stp_addr[i] |
0315                    (eth_stp_addr[i + 1] << 8));
0316         if (ret)
0317             return ret;
0318     }
0319 
0320     /* Mirror BPDU to CPU port */
0321     for (i = 0; i < ds->num_ports; i++) {
0322         if (dsa_is_cpu_port(ds, i))
0323             val |= BIT(i);
0324     }
0325 
0326     ret = regmap_write(priv->regmap, XRS_ETH_ADDR_FWD_MIRROR(port, 0), val);
0327     if (ret)
0328         return ret;
0329 
0330     ret = regmap_write(priv->regmap, XRS_ETH_ADDR_FWD_ALLOW(port, 0), 0);
0331     if (ret)
0332         return ret;
0333 
0334     return 0;
0335 }
0336 
0337 /* Add an inbound policy filter which matches the HSR/PRP supervision MAC
0338  * range and forwards to the CPU port without discarding duplicates.
0339  * This is required to correctly populate the HSR/PRP node_table.
0340  * Leave the policy disabled, it will be enabled as needed.
0341  */
0342 static int xrs700x_port_add_hsrsup_ipf(struct dsa_switch *ds, int port,
0343                        int fwdport)
0344 {
0345     struct xrs700x *priv = ds->priv;
0346     unsigned int val = 0;
0347     int i = 0;
0348     int ret;
0349 
0350     /* Compare 40 bits of the destination MAC address. */
0351     ret = regmap_write(priv->regmap, XRS_ETH_ADDR_CFG(port, 1), 40 << 2);
0352     if (ret)
0353         return ret;
0354 
0355     /* match HSR/PRP supervision destination 01:15:4e:00:01:XX */
0356     for (i = 0; i < sizeof(eth_hsrsup_addr); i += 2) {
0357         ret = regmap_write(priv->regmap, XRS_ETH_ADDR_0(port, 1) + i,
0358                    eth_hsrsup_addr[i] |
0359                    (eth_hsrsup_addr[i + 1] << 8));
0360         if (ret)
0361             return ret;
0362     }
0363 
0364     /* Mirror HSR/PRP supervision to CPU port */
0365     for (i = 0; i < ds->num_ports; i++) {
0366         if (dsa_is_cpu_port(ds, i))
0367             val |= BIT(i);
0368     }
0369 
0370     ret = regmap_write(priv->regmap, XRS_ETH_ADDR_FWD_MIRROR(port, 1), val);
0371     if (ret)
0372         return ret;
0373 
0374     if (fwdport >= 0)
0375         val |= BIT(fwdport);
0376 
0377     /* Allow must be set prevent duplicate discard */
0378     ret = regmap_write(priv->regmap, XRS_ETH_ADDR_FWD_ALLOW(port, 1), val);
0379     if (ret)
0380         return ret;
0381 
0382     return 0;
0383 }
0384 
0385 static int xrs700x_port_setup(struct dsa_switch *ds, int port)
0386 {
0387     bool cpu_port = dsa_is_cpu_port(ds, port);
0388     struct xrs700x *priv = ds->priv;
0389     unsigned int val = 0;
0390     int ret, i;
0391 
0392     xrs700x_port_stp_state_set(ds, port, BR_STATE_DISABLED);
0393 
0394     /* Disable forwarding to non-CPU ports */
0395     for (i = 0; i < ds->num_ports; i++) {
0396         if (!dsa_is_cpu_port(ds, i))
0397             val |= BIT(i);
0398     }
0399 
0400     /* 1 = Disable forwarding to the port */
0401     ret = regmap_write(priv->regmap, XRS_PORT_FWD_MASK(port), val);
0402     if (ret)
0403         return ret;
0404 
0405     val = cpu_port ? XRS_PORT_MODE_MANAGEMENT : XRS_PORT_MODE_NORMAL;
0406     ret = regmap_fields_write(priv->ps_management, port, val);
0407     if (ret)
0408         return ret;
0409 
0410     if (!cpu_port) {
0411         ret = xrs700x_port_add_bpdu_ipf(ds, port);
0412         if (ret)
0413             return ret;
0414     }
0415 
0416     return 0;
0417 }
0418 
0419 static int xrs700x_setup(struct dsa_switch *ds)
0420 {
0421     struct xrs700x *priv = ds->priv;
0422     int ret, i;
0423 
0424     ret = xrs700x_reset(ds);
0425     if (ret)
0426         return ret;
0427 
0428     for (i = 0; i < ds->num_ports; i++) {
0429         ret = xrs700x_port_setup(ds, i);
0430         if (ret)
0431             return ret;
0432     }
0433 
0434     schedule_delayed_work(&priv->mib_work, XRS700X_MIB_INTERVAL);
0435 
0436     return 0;
0437 }
0438 
0439 static void xrs700x_teardown(struct dsa_switch *ds)
0440 {
0441     struct xrs700x *priv = ds->priv;
0442 
0443     cancel_delayed_work_sync(&priv->mib_work);
0444 }
0445 
0446 static void xrs700x_phylink_get_caps(struct dsa_switch *ds, int port,
0447                      struct phylink_config *config)
0448 {
0449     switch (port) {
0450     case 0:
0451         __set_bit(PHY_INTERFACE_MODE_RMII,
0452               config->supported_interfaces);
0453         config->mac_capabilities = MAC_10FD | MAC_100FD;
0454         break;
0455 
0456     case 1:
0457     case 2:
0458     case 3:
0459         phy_interface_set_rgmii(config->supported_interfaces);
0460         config->mac_capabilities = MAC_10FD | MAC_100FD | MAC_1000FD;
0461         break;
0462 
0463     default:
0464         dev_err(ds->dev, "Unsupported port: %i\n", port);
0465         break;
0466     }
0467 }
0468 
0469 static void xrs700x_mac_link_up(struct dsa_switch *ds, int port,
0470                 unsigned int mode, phy_interface_t interface,
0471                 struct phy_device *phydev,
0472                 int speed, int duplex,
0473                 bool tx_pause, bool rx_pause)
0474 {
0475     struct xrs700x *priv = ds->priv;
0476     unsigned int val;
0477 
0478     switch (speed) {
0479     case SPEED_1000:
0480         val = XRS_PORT_SPEED_1000;
0481         break;
0482     case SPEED_100:
0483         val = XRS_PORT_SPEED_100;
0484         break;
0485     case SPEED_10:
0486         val = XRS_PORT_SPEED_10;
0487         break;
0488     default:
0489         return;
0490     }
0491 
0492     regmap_fields_write(priv->ps_sel_speed, port, val);
0493 
0494     dev_dbg_ratelimited(priv->dev, "%s: port: %d mode: %u speed: %u\n",
0495                 __func__, port, mode, speed);
0496 }
0497 
0498 static int xrs700x_bridge_common(struct dsa_switch *ds, int port,
0499                  struct dsa_bridge bridge, bool join)
0500 {
0501     unsigned int i, cpu_mask = 0, mask = 0;
0502     struct xrs700x *priv = ds->priv;
0503     int ret;
0504 
0505     for (i = 0; i < ds->num_ports; i++) {
0506         if (dsa_is_cpu_port(ds, i))
0507             continue;
0508 
0509         cpu_mask |= BIT(i);
0510 
0511         if (dsa_port_offloads_bridge(dsa_to_port(ds, i), &bridge))
0512             continue;
0513 
0514         mask |= BIT(i);
0515     }
0516 
0517     for (i = 0; i < ds->num_ports; i++) {
0518         if (!dsa_port_offloads_bridge(dsa_to_port(ds, i), &bridge))
0519             continue;
0520 
0521         /* 1 = Disable forwarding to the port */
0522         ret = regmap_write(priv->regmap, XRS_PORT_FWD_MASK(i), mask);
0523         if (ret)
0524             return ret;
0525     }
0526 
0527     if (!join) {
0528         ret = regmap_write(priv->regmap, XRS_PORT_FWD_MASK(port),
0529                    cpu_mask);
0530         if (ret)
0531             return ret;
0532     }
0533 
0534     return 0;
0535 }
0536 
0537 static int xrs700x_bridge_join(struct dsa_switch *ds, int port,
0538                    struct dsa_bridge bridge, bool *tx_fwd_offload,
0539                    struct netlink_ext_ack *extack)
0540 {
0541     return xrs700x_bridge_common(ds, port, bridge, true);
0542 }
0543 
0544 static void xrs700x_bridge_leave(struct dsa_switch *ds, int port,
0545                  struct dsa_bridge bridge)
0546 {
0547     xrs700x_bridge_common(ds, port, bridge, false);
0548 }
0549 
0550 static int xrs700x_hsr_join(struct dsa_switch *ds, int port,
0551                 struct net_device *hsr)
0552 {
0553     unsigned int val = XRS_HSR_CFG_HSR_PRP;
0554     struct dsa_port *partner = NULL, *dp;
0555     struct xrs700x *priv = ds->priv;
0556     struct net_device *slave;
0557     int ret, i, hsr_pair[2];
0558     enum hsr_version ver;
0559     bool fwd = false;
0560 
0561     ret = hsr_get_version(hsr, &ver);
0562     if (ret)
0563         return ret;
0564 
0565     /* Only ports 1 and 2 can be HSR/PRP redundant ports. */
0566     if (port != 1 && port != 2)
0567         return -EOPNOTSUPP;
0568 
0569     if (ver == HSR_V1)
0570         val |= XRS_HSR_CFG_HSR;
0571     else if (ver == PRP_V1)
0572         val |= XRS_HSR_CFG_PRP;
0573     else
0574         return -EOPNOTSUPP;
0575 
0576     dsa_hsr_foreach_port(dp, ds, hsr) {
0577         if (dp->index != port) {
0578             partner = dp;
0579             break;
0580         }
0581     }
0582 
0583     /* We can't enable redundancy on the switch until both
0584      * redundant ports have signed up.
0585      */
0586     if (!partner)
0587         return 0;
0588 
0589     regmap_fields_write(priv->ps_forward, partner->index,
0590                 XRS_PORT_DISABLED);
0591     regmap_fields_write(priv->ps_forward, port, XRS_PORT_DISABLED);
0592 
0593     regmap_write(priv->regmap, XRS_HSR_CFG(partner->index),
0594              val | XRS_HSR_CFG_LANID_A);
0595     regmap_write(priv->regmap, XRS_HSR_CFG(port),
0596              val | XRS_HSR_CFG_LANID_B);
0597 
0598     /* Clear bits for both redundant ports (HSR only) and the CPU port to
0599      * enable forwarding.
0600      */
0601     val = GENMASK(ds->num_ports - 1, 0);
0602     if (ver == HSR_V1) {
0603         val &= ~BIT(partner->index);
0604         val &= ~BIT(port);
0605         fwd = true;
0606     }
0607     val &= ~BIT(dsa_upstream_port(ds, port));
0608     regmap_write(priv->regmap, XRS_PORT_FWD_MASK(partner->index), val);
0609     regmap_write(priv->regmap, XRS_PORT_FWD_MASK(port), val);
0610 
0611     regmap_fields_write(priv->ps_forward, partner->index,
0612                 XRS_PORT_FORWARDING);
0613     regmap_fields_write(priv->ps_forward, port, XRS_PORT_FORWARDING);
0614 
0615     /* Enable inbound policy which allows HSR/PRP supervision forwarding
0616      * to the CPU port without discarding duplicates. Continue to
0617      * forward to redundant ports when in HSR mode while discarding
0618      * duplicates.
0619      */
0620     ret = xrs700x_port_add_hsrsup_ipf(ds, partner->index, fwd ? port : -1);
0621     if (ret)
0622         return ret;
0623 
0624     ret = xrs700x_port_add_hsrsup_ipf(ds, port, fwd ? partner->index : -1);
0625     if (ret)
0626         return ret;
0627 
0628     regmap_update_bits(priv->regmap,
0629                XRS_ETH_ADDR_CFG(partner->index, 1), 1, 1);
0630     regmap_update_bits(priv->regmap, XRS_ETH_ADDR_CFG(port, 1), 1, 1);
0631 
0632     hsr_pair[0] = port;
0633     hsr_pair[1] = partner->index;
0634     for (i = 0; i < ARRAY_SIZE(hsr_pair); i++) {
0635         slave = dsa_to_port(ds, hsr_pair[i])->slave;
0636         slave->features |= XRS7000X_SUPPORTED_HSR_FEATURES;
0637     }
0638 
0639     return 0;
0640 }
0641 
0642 static int xrs700x_hsr_leave(struct dsa_switch *ds, int port,
0643                  struct net_device *hsr)
0644 {
0645     struct dsa_port *partner = NULL, *dp;
0646     struct xrs700x *priv = ds->priv;
0647     struct net_device *slave;
0648     int i, hsr_pair[2];
0649     unsigned int val;
0650 
0651     dsa_hsr_foreach_port(dp, ds, hsr) {
0652         if (dp->index != port) {
0653             partner = dp;
0654             break;
0655         }
0656     }
0657 
0658     if (!partner)
0659         return 0;
0660 
0661     regmap_fields_write(priv->ps_forward, partner->index,
0662                 XRS_PORT_DISABLED);
0663     regmap_fields_write(priv->ps_forward, port, XRS_PORT_DISABLED);
0664 
0665     regmap_write(priv->regmap, XRS_HSR_CFG(partner->index), 0);
0666     regmap_write(priv->regmap, XRS_HSR_CFG(port), 0);
0667 
0668     /* Clear bit for the CPU port to enable forwarding. */
0669     val = GENMASK(ds->num_ports - 1, 0);
0670     val &= ~BIT(dsa_upstream_port(ds, port));
0671     regmap_write(priv->regmap, XRS_PORT_FWD_MASK(partner->index), val);
0672     regmap_write(priv->regmap, XRS_PORT_FWD_MASK(port), val);
0673 
0674     regmap_fields_write(priv->ps_forward, partner->index,
0675                 XRS_PORT_FORWARDING);
0676     regmap_fields_write(priv->ps_forward, port, XRS_PORT_FORWARDING);
0677 
0678     /* Disable inbound policy added by xrs700x_port_add_hsrsup_ipf()
0679      * which allows HSR/PRP supervision forwarding to the CPU port without
0680      * discarding duplicates.
0681      */
0682     regmap_update_bits(priv->regmap,
0683                XRS_ETH_ADDR_CFG(partner->index, 1), 1, 0);
0684     regmap_update_bits(priv->regmap, XRS_ETH_ADDR_CFG(port, 1), 1, 0);
0685 
0686     hsr_pair[0] = port;
0687     hsr_pair[1] = partner->index;
0688     for (i = 0; i < ARRAY_SIZE(hsr_pair); i++) {
0689         slave = dsa_to_port(ds, hsr_pair[i])->slave;
0690         slave->features &= ~XRS7000X_SUPPORTED_HSR_FEATURES;
0691     }
0692 
0693     return 0;
0694 }
0695 
0696 static const struct dsa_switch_ops xrs700x_ops = {
0697     .get_tag_protocol   = xrs700x_get_tag_protocol,
0698     .setup          = xrs700x_setup,
0699     .teardown       = xrs700x_teardown,
0700     .port_stp_state_set = xrs700x_port_stp_state_set,
0701     .phylink_get_caps   = xrs700x_phylink_get_caps,
0702     .phylink_mac_link_up    = xrs700x_mac_link_up,
0703     .get_strings        = xrs700x_get_strings,
0704     .get_sset_count     = xrs700x_get_sset_count,
0705     .get_ethtool_stats  = xrs700x_get_ethtool_stats,
0706     .get_stats64        = xrs700x_get_stats64,
0707     .port_bridge_join   = xrs700x_bridge_join,
0708     .port_bridge_leave  = xrs700x_bridge_leave,
0709     .port_hsr_join      = xrs700x_hsr_join,
0710     .port_hsr_leave     = xrs700x_hsr_leave,
0711 };
0712 
0713 static int xrs700x_detect(struct xrs700x *priv)
0714 {
0715     const struct xrs700x_info *info;
0716     unsigned int id;
0717     int ret;
0718 
0719     ret = regmap_read(priv->regmap, XRS_DEV_ID0, &id);
0720     if (ret) {
0721         dev_err(priv->dev, "error %d while reading switch id.\n",
0722             ret);
0723         return ret;
0724     }
0725 
0726     info = of_device_get_match_data(priv->dev);
0727     if (!info)
0728         return -EINVAL;
0729 
0730     if (info->id == id) {
0731         priv->ds->num_ports = info->num_ports;
0732         dev_info(priv->dev, "%s detected.\n", info->name);
0733         return 0;
0734     }
0735 
0736     dev_err(priv->dev, "expected switch id 0x%x but found 0x%x.\n",
0737         info->id, id);
0738 
0739     return -ENODEV;
0740 }
0741 
0742 struct xrs700x *xrs700x_switch_alloc(struct device *base, void *devpriv)
0743 {
0744     struct dsa_switch *ds;
0745     struct xrs700x *priv;
0746 
0747     ds = devm_kzalloc(base, sizeof(*ds), GFP_KERNEL);
0748     if (!ds)
0749         return NULL;
0750 
0751     ds->dev = base;
0752 
0753     priv = devm_kzalloc(base, sizeof(*priv), GFP_KERNEL);
0754     if (!priv)
0755         return NULL;
0756 
0757     INIT_DELAYED_WORK(&priv->mib_work, xrs700x_mib_work);
0758 
0759     ds->ops = &xrs700x_ops;
0760     ds->priv = priv;
0761     priv->dev = base;
0762 
0763     priv->ds = ds;
0764     priv->priv = devpriv;
0765 
0766     return priv;
0767 }
0768 EXPORT_SYMBOL(xrs700x_switch_alloc);
0769 
0770 static int xrs700x_alloc_port_mib(struct xrs700x *priv, int port)
0771 {
0772     struct xrs700x_port *p = &priv->ports[port];
0773 
0774     p->mib_data = devm_kcalloc(priv->dev, ARRAY_SIZE(xrs700x_mibs),
0775                    sizeof(*p->mib_data), GFP_KERNEL);
0776     if (!p->mib_data)
0777         return -ENOMEM;
0778 
0779     mutex_init(&p->mib_mutex);
0780     u64_stats_init(&p->syncp);
0781 
0782     return 0;
0783 }
0784 
0785 int xrs700x_switch_register(struct xrs700x *priv)
0786 {
0787     int ret;
0788     int i;
0789 
0790     ret = xrs700x_detect(priv);
0791     if (ret)
0792         return ret;
0793 
0794     ret = xrs700x_setup_regmap_range(priv);
0795     if (ret)
0796         return ret;
0797 
0798     priv->ports = devm_kcalloc(priv->dev, priv->ds->num_ports,
0799                    sizeof(*priv->ports), GFP_KERNEL);
0800     if (!priv->ports)
0801         return -ENOMEM;
0802 
0803     for (i = 0; i < priv->ds->num_ports; i++) {
0804         ret = xrs700x_alloc_port_mib(priv, i);
0805         if (ret)
0806             return ret;
0807     }
0808 
0809     return dsa_register_switch(priv->ds);
0810 }
0811 EXPORT_SYMBOL(xrs700x_switch_register);
0812 
0813 void xrs700x_switch_remove(struct xrs700x *priv)
0814 {
0815     dsa_unregister_switch(priv->ds);
0816 }
0817 EXPORT_SYMBOL(xrs700x_switch_remove);
0818 
0819 void xrs700x_switch_shutdown(struct xrs700x *priv)
0820 {
0821     dsa_switch_shutdown(priv->ds);
0822 }
0823 EXPORT_SYMBOL(xrs700x_switch_shutdown);
0824 
0825 MODULE_AUTHOR("George McCollister <george.mccollister@gmail.com>");
0826 MODULE_DESCRIPTION("Arrow SpeedChips XRS700x DSA driver");
0827 MODULE_LICENSE("GPL v2");