1 /* 2 * Handling of a master device, switching frames via its switch fabric CPU port 3 * 4 * Copyright (c) 2017 Savoir-faire Linux Inc. 5 * Vivien Didelot <vivien.didelot@savoirfairelinux.com> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 */ 12 13 #include "dsa_priv.h" 14 15 static void dsa_master_get_ethtool_stats(struct net_device *dev, 16 struct ethtool_stats *stats, 17 uint64_t *data) 18 { 19 struct dsa_port *cpu_dp = dev->dsa_ptr; 20 const struct ethtool_ops *ops = cpu_dp->orig_ethtool_ops; 21 struct dsa_switch *ds = cpu_dp->ds; 22 int port = cpu_dp->index; 23 int count = 0; 24 25 if (ops->get_sset_count && ops->get_ethtool_stats) { 26 count = ops->get_sset_count(dev, ETH_SS_STATS); 27 ops->get_ethtool_stats(dev, stats, data); 28 } 29 30 if (ds->ops->get_ethtool_stats) 31 ds->ops->get_ethtool_stats(ds, port, data + count); 32 } 33 34 static void dsa_master_get_ethtool_phy_stats(struct net_device *dev, 35 struct ethtool_stats *stats, 36 uint64_t *data) 37 { 38 struct dsa_port *cpu_dp = dev->dsa_ptr; 39 const struct ethtool_ops *ops = cpu_dp->orig_ethtool_ops; 40 struct dsa_switch *ds = cpu_dp->ds; 41 int port = cpu_dp->index; 42 int count = 0; 43 44 if (dev->phydev && !ops->get_ethtool_phy_stats) { 45 count = phy_ethtool_get_sset_count(dev->phydev); 46 if (count >= 0) 47 phy_ethtool_get_stats(dev->phydev, stats, data); 48 } else if (ops->get_sset_count && ops->get_ethtool_phy_stats) { 49 count = ops->get_sset_count(dev, ETH_SS_PHY_STATS); 50 ops->get_ethtool_phy_stats(dev, stats, data); 51 } 52 53 if (count < 0) 54 count = 0; 55 56 if (ds->ops->get_ethtool_phy_stats) 57 ds->ops->get_ethtool_phy_stats(ds, port, data + count); 58 } 59 60 static int dsa_master_get_sset_count(struct net_device *dev, int sset) 61 { 62 struct dsa_port *cpu_dp = dev->dsa_ptr; 63 const struct ethtool_ops *ops = cpu_dp->orig_ethtool_ops; 64 struct dsa_switch *ds = cpu_dp->ds; 65 int count = 0; 66 67 if (sset == ETH_SS_PHY_STATS && dev->phydev && 68 !ops->get_ethtool_phy_stats) 69 count = phy_ethtool_get_sset_count(dev->phydev); 70 else if (ops->get_sset_count) 71 count = ops->get_sset_count(dev, sset); 72 73 if (count < 0) 74 count = 0; 75 76 if (ds->ops->get_sset_count) 77 count += ds->ops->get_sset_count(ds, cpu_dp->index, sset); 78 79 return count; 80 } 81 82 static void dsa_master_get_strings(struct net_device *dev, uint32_t stringset, 83 uint8_t *data) 84 { 85 struct dsa_port *cpu_dp = dev->dsa_ptr; 86 const struct ethtool_ops *ops = cpu_dp->orig_ethtool_ops; 87 struct dsa_switch *ds = cpu_dp->ds; 88 int port = cpu_dp->index; 89 int len = ETH_GSTRING_LEN; 90 int mcount = 0, count; 91 unsigned int i; 92 uint8_t pfx[4]; 93 uint8_t *ndata; 94 95 snprintf(pfx, sizeof(pfx), "p%.2d", port); 96 /* We do not want to be NULL-terminated, since this is a prefix */ 97 pfx[sizeof(pfx) - 1] = '_'; 98 99 if (stringset == ETH_SS_PHY_STATS && dev->phydev && 100 !ops->get_ethtool_phy_stats) { 101 mcount = phy_ethtool_get_sset_count(dev->phydev); 102 if (mcount < 0) 103 mcount = 0; 104 else 105 phy_ethtool_get_strings(dev->phydev, data); 106 } else if (ops->get_sset_count && ops->get_strings) { 107 mcount = ops->get_sset_count(dev, stringset); 108 if (mcount < 0) 109 mcount = 0; 110 ops->get_strings(dev, stringset, data); 111 } 112 113 if (ds->ops->get_strings) { 114 ndata = data + mcount * len; 115 /* This function copies ETH_GSTRINGS_LEN bytes, we will mangle 116 * the output after to prepend our CPU port prefix we 117 * constructed earlier 118 */ 119 ds->ops->get_strings(ds, port, stringset, ndata); 120 count = ds->ops->get_sset_count(ds, port, stringset); 121 for (i = 0; i < count; i++) { 122 memmove(ndata + (i * len + sizeof(pfx)), 123 ndata + i * len, len - sizeof(pfx)); 124 memcpy(ndata + i * len, pfx, sizeof(pfx)); 125 } 126 } 127 } 128 129 static int dsa_master_get_phys_port_name(struct net_device *dev, 130 char *name, size_t len) 131 { 132 struct dsa_port *cpu_dp = dev->dsa_ptr; 133 134 if (snprintf(name, len, "p%d", cpu_dp->index) >= len) 135 return -EINVAL; 136 137 return 0; 138 } 139 140 static int dsa_master_ethtool_setup(struct net_device *dev) 141 { 142 struct dsa_port *cpu_dp = dev->dsa_ptr; 143 struct dsa_switch *ds = cpu_dp->ds; 144 struct ethtool_ops *ops; 145 146 ops = devm_kzalloc(ds->dev, sizeof(*ops), GFP_KERNEL); 147 if (!ops) 148 return -ENOMEM; 149 150 cpu_dp->orig_ethtool_ops = dev->ethtool_ops; 151 if (cpu_dp->orig_ethtool_ops) 152 memcpy(ops, cpu_dp->orig_ethtool_ops, sizeof(*ops)); 153 154 ops->get_sset_count = dsa_master_get_sset_count; 155 ops->get_ethtool_stats = dsa_master_get_ethtool_stats; 156 ops->get_strings = dsa_master_get_strings; 157 ops->get_ethtool_phy_stats = dsa_master_get_ethtool_phy_stats; 158 159 dev->ethtool_ops = ops; 160 161 return 0; 162 } 163 164 static void dsa_master_ethtool_teardown(struct net_device *dev) 165 { 166 struct dsa_port *cpu_dp = dev->dsa_ptr; 167 168 dev->ethtool_ops = cpu_dp->orig_ethtool_ops; 169 cpu_dp->orig_ethtool_ops = NULL; 170 } 171 172 static int dsa_master_ndo_setup(struct net_device *dev) 173 { 174 struct dsa_port *cpu_dp = dev->dsa_ptr; 175 struct dsa_switch *ds = cpu_dp->ds; 176 struct net_device_ops *ops; 177 178 if (dev->netdev_ops->ndo_get_phys_port_name) 179 return 0; 180 181 ops = devm_kzalloc(ds->dev, sizeof(*ops), GFP_KERNEL); 182 if (!ops) 183 return -ENOMEM; 184 185 cpu_dp->orig_ndo_ops = dev->netdev_ops; 186 if (cpu_dp->orig_ndo_ops) 187 memcpy(ops, cpu_dp->orig_ndo_ops, sizeof(*ops)); 188 189 ops->ndo_get_phys_port_name = dsa_master_get_phys_port_name; 190 191 dev->netdev_ops = ops; 192 193 return 0; 194 } 195 196 static void dsa_master_ndo_teardown(struct net_device *dev) 197 { 198 struct dsa_port *cpu_dp = dev->dsa_ptr; 199 200 dev->netdev_ops = cpu_dp->orig_ndo_ops; 201 cpu_dp->orig_ndo_ops = NULL; 202 } 203 204 static ssize_t tagging_show(struct device *d, struct device_attribute *attr, 205 char *buf) 206 { 207 struct net_device *dev = to_net_dev(d); 208 struct dsa_port *cpu_dp = dev->dsa_ptr; 209 210 return sprintf(buf, "%s\n", 211 dsa_tag_protocol_to_str(cpu_dp->tag_ops)); 212 } 213 static DEVICE_ATTR_RO(tagging); 214 215 static struct attribute *dsa_slave_attrs[] = { 216 &dev_attr_tagging.attr, 217 NULL 218 }; 219 220 static const struct attribute_group dsa_group = { 221 .name = "dsa", 222 .attrs = dsa_slave_attrs, 223 }; 224 225 static void dsa_master_set_mtu(struct net_device *dev, struct dsa_port *cpu_dp) 226 { 227 unsigned int mtu = ETH_DATA_LEN + cpu_dp->tag_ops->overhead; 228 int err; 229 230 rtnl_lock(); 231 if (mtu <= dev->max_mtu) { 232 err = dev_set_mtu(dev, mtu); 233 if (err) 234 netdev_dbg(dev, "Unable to set MTU to include for DSA overheads\n"); 235 } 236 rtnl_unlock(); 237 } 238 239 static void dsa_master_reset_mtu(struct net_device *dev) 240 { 241 int err; 242 243 rtnl_lock(); 244 err = dev_set_mtu(dev, ETH_DATA_LEN); 245 if (err) 246 netdev_dbg(dev, 247 "Unable to reset MTU to exclude DSA overheads\n"); 248 rtnl_unlock(); 249 } 250 251 static struct lock_class_key dsa_master_addr_list_lock_key; 252 253 int dsa_master_setup(struct net_device *dev, struct dsa_port *cpu_dp) 254 { 255 int ret; 256 257 dsa_master_set_mtu(dev, cpu_dp); 258 259 /* If we use a tagging format that doesn't have an ethertype 260 * field, make sure that all packets from this point on get 261 * sent to the tag format's receive function. 262 */ 263 wmb(); 264 265 dev->dsa_ptr = cpu_dp; 266 lockdep_set_class(&dev->addr_list_lock, 267 &dsa_master_addr_list_lock_key); 268 269 ret = dsa_master_ethtool_setup(dev); 270 if (ret) 271 return ret; 272 273 ret = dsa_master_ndo_setup(dev); 274 if (ret) 275 goto out_err_ethtool_teardown; 276 277 ret = sysfs_create_group(&dev->dev.kobj, &dsa_group); 278 if (ret) 279 goto out_err_ndo_teardown; 280 281 return ret; 282 283 out_err_ndo_teardown: 284 dsa_master_ndo_teardown(dev); 285 out_err_ethtool_teardown: 286 dsa_master_ethtool_teardown(dev); 287 return ret; 288 } 289 290 void dsa_master_teardown(struct net_device *dev) 291 { 292 sysfs_remove_group(&dev->dev.kobj, &dsa_group); 293 dsa_master_ndo_teardown(dev); 294 dsa_master_ethtool_teardown(dev); 295 dsa_master_reset_mtu(dev); 296 297 dev->dsa_ptr = NULL; 298 299 /* If we used a tagging format that doesn't have an ethertype 300 * field, make sure that all packets from this point get sent 301 * without the tag and go through the regular receive path. 302 */ 303 wmb(); 304 } 305