^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Distributed Switch Architecture loopback driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2016, Florian Fainelli <f.fainelli@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/phy.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/phy_fixed.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/ethtool.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/workqueue.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/if_bridge.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/dsa/loop.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <net/dsa.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "dsa_loop.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) static struct dsa_loop_mib_entry dsa_loop_mibs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) [DSA_LOOP_PHY_READ_OK] = { "phy_read_ok", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) [DSA_LOOP_PHY_READ_ERR] = { "phy_read_err", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) [DSA_LOOP_PHY_WRITE_OK] = { "phy_write_ok", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) [DSA_LOOP_PHY_WRITE_ERR] = { "phy_write_err", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) static struct phy_device *phydevs[PHY_MAX_ADDR];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) enum dsa_loop_devlink_resource_id {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) DSA_LOOP_DEVLINK_PARAM_ID_VTU,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) static u64 dsa_loop_devlink_vtu_get(void *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) struct dsa_loop_priv *ps = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) unsigned int i, count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) struct dsa_loop_vlan *vl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) for (i = 0; i < ARRAY_SIZE(ps->vlans); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) vl = &ps->vlans[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) if (vl->members)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) static int dsa_loop_setup_devlink_resources(struct dsa_switch *ds)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) struct devlink_resource_size_params size_params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) struct dsa_loop_priv *ps = ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) devlink_resource_size_params_init(&size_params, ARRAY_SIZE(ps->vlans),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) ARRAY_SIZE(ps->vlans),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) 1, DEVLINK_RESOURCE_UNIT_ENTRY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) err = dsa_devlink_resource_register(ds, "VTU", ARRAY_SIZE(ps->vlans),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) DSA_LOOP_DEVLINK_PARAM_ID_VTU,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) DEVLINK_RESOURCE_ID_PARENT_TOP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) &size_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) dsa_devlink_resource_occ_get_register(ds,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) DSA_LOOP_DEVLINK_PARAM_ID_VTU,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) dsa_loop_devlink_vtu_get, ps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) dsa_devlink_resources_unregister(ds);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) static enum dsa_tag_protocol dsa_loop_get_protocol(struct dsa_switch *ds,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) enum dsa_tag_protocol mp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) dev_dbg(ds->dev, "%s: port: %d\n", __func__, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return DSA_TAG_PROTO_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) static int dsa_loop_setup(struct dsa_switch *ds)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) struct dsa_loop_priv *ps = ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) for (i = 0; i < ds->num_ports; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) memcpy(ps->ports[i].mib, dsa_loop_mibs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) sizeof(dsa_loop_mibs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) dev_dbg(ds->dev, "%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) return dsa_loop_setup_devlink_resources(ds);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static void dsa_loop_teardown(struct dsa_switch *ds)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) dsa_devlink_resources_unregister(ds);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) static int dsa_loop_get_sset_count(struct dsa_switch *ds, int port, int sset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) if (sset != ETH_SS_STATS && sset != ETH_SS_PHY_STATS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) return __DSA_LOOP_CNT_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) static void dsa_loop_get_strings(struct dsa_switch *ds, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) u32 stringset, uint8_t *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) struct dsa_loop_priv *ps = ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) if (stringset != ETH_SS_STATS && stringset != ETH_SS_PHY_STATS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) for (i = 0; i < __DSA_LOOP_CNT_MAX; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) memcpy(data + i * ETH_GSTRING_LEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) ps->ports[port].mib[i].name, ETH_GSTRING_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) static void dsa_loop_get_ethtool_stats(struct dsa_switch *ds, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) uint64_t *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) struct dsa_loop_priv *ps = ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) for (i = 0; i < __DSA_LOOP_CNT_MAX; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) data[i] = ps->ports[port].mib[i].val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) static int dsa_loop_phy_read(struct dsa_switch *ds, int port, int regnum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) struct dsa_loop_priv *ps = ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) struct mii_bus *bus = ps->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) ret = mdiobus_read_nested(bus, ps->port_base + port, regnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) ps->ports[port].mib[DSA_LOOP_PHY_READ_ERR].val++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) ps->ports[port].mib[DSA_LOOP_PHY_READ_OK].val++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) static int dsa_loop_phy_write(struct dsa_switch *ds, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) int regnum, u16 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) struct dsa_loop_priv *ps = ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) struct mii_bus *bus = ps->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) ret = mdiobus_write_nested(bus, ps->port_base + port, regnum, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) ps->ports[port].mib[DSA_LOOP_PHY_WRITE_ERR].val++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) ps->ports[port].mib[DSA_LOOP_PHY_WRITE_OK].val++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) static int dsa_loop_port_bridge_join(struct dsa_switch *ds, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) struct net_device *bridge)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) dev_dbg(ds->dev, "%s: port: %d, bridge: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) __func__, port, bridge->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) static void dsa_loop_port_bridge_leave(struct dsa_switch *ds, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) struct net_device *bridge)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) dev_dbg(ds->dev, "%s: port: %d, bridge: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) __func__, port, bridge->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) static void dsa_loop_port_stp_state_set(struct dsa_switch *ds, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) u8 state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) dev_dbg(ds->dev, "%s: port: %d, state: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) __func__, port, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) static int dsa_loop_port_vlan_filtering(struct dsa_switch *ds, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) bool vlan_filtering,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) struct switchdev_trans *trans)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) dev_dbg(ds->dev, "%s: port: %d, vlan_filtering: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) __func__, port, vlan_filtering);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) dsa_loop_port_vlan_prepare(struct dsa_switch *ds, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) const struct switchdev_obj_port_vlan *vlan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) struct dsa_loop_priv *ps = ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) struct mii_bus *bus = ps->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) dev_dbg(ds->dev, "%s: port: %d, vlan: %d-%d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) __func__, port, vlan->vid_begin, vlan->vid_end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) /* Just do a sleeping operation to make lockdep checks effective */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) mdiobus_read(bus, ps->port_base + port, MII_BMSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) if (vlan->vid_end > ARRAY_SIZE(ps->vlans))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) return -ERANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) static void dsa_loop_port_vlan_add(struct dsa_switch *ds, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) const struct switchdev_obj_port_vlan *vlan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) struct dsa_loop_priv *ps = ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) struct mii_bus *bus = ps->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) struct dsa_loop_vlan *vl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) u16 vid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) /* Just do a sleeping operation to make lockdep checks effective */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) mdiobus_read(bus, ps->port_base + port, MII_BMSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) vl = &ps->vlans[vid];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) vl->members |= BIT(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) if (untagged)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) vl->untagged |= BIT(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) vl->untagged &= ~BIT(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) dev_dbg(ds->dev, "%s: port: %d vlan: %d, %stagged, pvid: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) __func__, port, vid, untagged ? "un" : "", pvid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) if (pvid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) ps->ports[port].pvid = vid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) static int dsa_loop_port_vlan_del(struct dsa_switch *ds, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) const struct switchdev_obj_port_vlan *vlan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) struct dsa_loop_priv *ps = ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) struct mii_bus *bus = ps->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) struct dsa_loop_vlan *vl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) u16 vid, pvid = ps->ports[port].pvid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) /* Just do a sleeping operation to make lockdep checks effective */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) mdiobus_read(bus, ps->port_base + port, MII_BMSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) vl = &ps->vlans[vid];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) vl->members &= ~BIT(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (untagged)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) vl->untagged &= ~BIT(port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) if (pvid == vid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) pvid = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) dev_dbg(ds->dev, "%s: port: %d vlan: %d, %stagged, pvid: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) __func__, port, vid, untagged ? "un" : "", pvid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) ps->ports[port].pvid = pvid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) static int dsa_loop_port_change_mtu(struct dsa_switch *ds, int port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) int new_mtu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) struct dsa_loop_priv *priv = ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) priv->ports[port].mtu = new_mtu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) static int dsa_loop_port_max_mtu(struct dsa_switch *ds, int port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) return ETH_MAX_MTU;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) static const struct dsa_switch_ops dsa_loop_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) .get_tag_protocol = dsa_loop_get_protocol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) .setup = dsa_loop_setup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) .teardown = dsa_loop_teardown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) .get_strings = dsa_loop_get_strings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) .get_ethtool_stats = dsa_loop_get_ethtool_stats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) .get_sset_count = dsa_loop_get_sset_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) .get_ethtool_phy_stats = dsa_loop_get_ethtool_stats,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) .phy_read = dsa_loop_phy_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) .phy_write = dsa_loop_phy_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) .port_bridge_join = dsa_loop_port_bridge_join,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) .port_bridge_leave = dsa_loop_port_bridge_leave,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) .port_stp_state_set = dsa_loop_port_stp_state_set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) .port_vlan_filtering = dsa_loop_port_vlan_filtering,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) .port_vlan_prepare = dsa_loop_port_vlan_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) .port_vlan_add = dsa_loop_port_vlan_add,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) .port_vlan_del = dsa_loop_port_vlan_del,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) .port_change_mtu = dsa_loop_port_change_mtu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) .port_max_mtu = dsa_loop_port_max_mtu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) static int dsa_loop_drv_probe(struct mdio_device *mdiodev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) struct dsa_loop_pdata *pdata = mdiodev->dev.platform_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) struct dsa_loop_priv *ps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) struct dsa_switch *ds;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) if (!pdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) ds = devm_kzalloc(&mdiodev->dev, sizeof(*ds), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) if (!ds)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) ds->dev = &mdiodev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) ds->num_ports = DSA_LOOP_NUM_PORTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) ps = devm_kzalloc(&mdiodev->dev, sizeof(*ps), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) if (!ps)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) ps->netdev = dev_get_by_name(&init_net, pdata->netdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) if (!ps->netdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) return -EPROBE_DEFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) pdata->cd.netdev[DSA_LOOP_CPU_PORT] = &ps->netdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) ds->dev = &mdiodev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) ds->ops = &dsa_loop_driver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) ds->priv = ps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) ds->configure_vlan_while_not_filtering = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) ps->bus = mdiodev->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) dev_set_drvdata(&mdiodev->dev, ds);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) ret = dsa_register_switch(ds);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) dev_info(&mdiodev->dev, "%s: 0x%0x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) pdata->name, pdata->enabled_ports);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) static void dsa_loop_drv_remove(struct mdio_device *mdiodev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) struct dsa_loop_priv *ps = ds->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) dsa_unregister_switch(ds);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) dev_put(ps->netdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) static struct mdio_driver dsa_loop_drv = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) .mdiodrv.driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) .name = "dsa-loop",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) .probe = dsa_loop_drv_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) .remove = dsa_loop_drv_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) #define NUM_FIXED_PHYS (DSA_LOOP_NUM_PORTS - 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) static int __init dsa_loop_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) struct fixed_phy_status status = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) .link = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) .speed = SPEED_100,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) .duplex = DUPLEX_FULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) for (i = 0; i < NUM_FIXED_PHYS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) phydevs[i] = fixed_phy_register(PHY_POLL, &status, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) return mdio_driver_register(&dsa_loop_drv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) module_init(dsa_loop_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) static void __exit dsa_loop_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) mdio_driver_unregister(&dsa_loop_drv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) for (i = 0; i < NUM_FIXED_PHYS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) if (!IS_ERR(phydevs[i]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) fixed_phy_unregister(phydevs[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) module_exit(dsa_loop_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) MODULE_SOFTDEP("pre: dsa_loop_bdinfo");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) MODULE_AUTHOR("Florian Fainelli");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) MODULE_DESCRIPTION("DSA loopback driver");