slave.c (bfcb813203e619a8960a819bf533ad2a108d8105) slave.c (bff33f7e2ae2e805a4b0af597b58422185c68900)
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * net/dsa/slave.c - Slave device handling
4 * Copyright (c) 2008-2009 Marvell Semiconductor
5 */
6
7#include <linux/list.h>
8#include <linux/etherdevice.h>

--- 1204 unchanged lines hidden (view full) ---

1213 }
1214
1215 /* Do not deprogram the CPU port as it may be shared with other user
1216 * ports which can be members of this VLAN as well.
1217 */
1218 return dsa_port_vid_del(dp, vid);
1219}
1220
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * net/dsa/slave.c - Slave device handling
4 * Copyright (c) 2008-2009 Marvell Semiconductor
5 */
6
7#include <linux/list.h>
8#include <linux/etherdevice.h>

--- 1204 unchanged lines hidden (view full) ---

1213 }
1214
1215 /* Do not deprogram the CPU port as it may be shared with other user
1216 * ports which can be members of this VLAN as well.
1217 */
1218 return dsa_port_vid_del(dp, vid);
1219}
1220
1221struct dsa_hw_port {
1222 struct list_head list;
1223 struct net_device *dev;
1224 int old_mtu;
1225};
1226
1227static int dsa_hw_port_list_set_mtu(struct list_head *hw_port_list, int mtu)
1228{
1229 const struct dsa_hw_port *p;
1230 int err;
1231
1232 list_for_each_entry(p, hw_port_list, list) {
1233 if (p->dev->mtu == mtu)
1234 continue;
1235
1236 err = dev_set_mtu(p->dev, mtu);
1237 if (err)
1238 goto rollback;
1239 }
1240
1241 return 0;
1242
1243rollback:
1244 list_for_each_entry_continue_reverse(p, hw_port_list, list) {
1245 if (p->dev->mtu == p->old_mtu)
1246 continue;
1247
1248 if (dev_set_mtu(p->dev, p->old_mtu))
1249 netdev_err(p->dev, "Failed to restore MTU\n");
1250 }
1251
1252 return err;
1253}
1254
1255static void dsa_hw_port_list_free(struct list_head *hw_port_list)
1256{
1257 struct dsa_hw_port *p, *n;
1258
1259 list_for_each_entry_safe(p, n, hw_port_list, list)
1260 kfree(p);
1261}
1262
1263/* Make the hardware datapath to/from @dev limited to a common MTU */
1264void dsa_bridge_mtu_normalization(struct dsa_port *dp)
1265{
1266 struct list_head hw_port_list;
1267 struct dsa_switch_tree *dst;
1268 int min_mtu = ETH_MAX_MTU;
1269 struct dsa_port *other_dp;
1270 int err;
1271
1272 if (!dp->ds->mtu_enforcement_ingress)
1273 return;
1274
1275 if (!dp->bridge_dev)
1276 return;
1277
1278 INIT_LIST_HEAD(&hw_port_list);
1279
1280 /* Populate the list of ports that are part of the same bridge
1281 * as the newly added/modified port
1282 */
1283 list_for_each_entry(dst, &dsa_tree_list, list) {
1284 list_for_each_entry(other_dp, &dst->ports, list) {
1285 struct dsa_hw_port *hw_port;
1286 struct net_device *slave;
1287
1288 if (other_dp->type != DSA_PORT_TYPE_USER)
1289 continue;
1290
1291 if (other_dp->bridge_dev != dp->bridge_dev)
1292 continue;
1293
1294 if (!other_dp->ds->mtu_enforcement_ingress)
1295 continue;
1296
1297 slave = other_dp->slave;
1298
1299 if (min_mtu > slave->mtu)
1300 min_mtu = slave->mtu;
1301
1302 hw_port = kzalloc(sizeof(*hw_port), GFP_KERNEL);
1303 if (!hw_port)
1304 goto out;
1305
1306 hw_port->dev = slave;
1307 hw_port->old_mtu = slave->mtu;
1308
1309 list_add(&hw_port->list, &hw_port_list);
1310 }
1311 }
1312
1313 /* Attempt to configure the entire hardware bridge to the newly added
1314 * interface's MTU first, regardless of whether the intention of the
1315 * user was to raise or lower it.
1316 */
1317 err = dsa_hw_port_list_set_mtu(&hw_port_list, dp->slave->mtu);
1318 if (!err)
1319 goto out;
1320
1321 /* Clearly that didn't work out so well, so just set the minimum MTU on
1322 * all hardware bridge ports now. If this fails too, then all ports will
1323 * still have their old MTU rolled back anyway.
1324 */
1325 dsa_hw_port_list_set_mtu(&hw_port_list, min_mtu);
1326
1327out:
1328 dsa_hw_port_list_free(&hw_port_list);
1329}
1330
1221static int dsa_slave_change_mtu(struct net_device *dev, int new_mtu)
1222{
1223 struct net_device *master = dsa_slave_to_master(dev);
1224 struct dsa_port *dp = dsa_slave_to_port(dev);
1225 struct dsa_slave_priv *p = netdev_priv(dev);
1226 struct dsa_switch *ds = p->dp->ds;
1227 struct dsa_port *cpu_dp;
1228 int port = p->dp->index;

--- 60 unchanged lines hidden (view full) ---

1289 }
1290
1291 err = dsa_port_mtu_change(dp, new_mtu, false);
1292 if (err)
1293 goto out_port_failed;
1294
1295 dev->mtu = new_mtu;
1296
1331static int dsa_slave_change_mtu(struct net_device *dev, int new_mtu)
1332{
1333 struct net_device *master = dsa_slave_to_master(dev);
1334 struct dsa_port *dp = dsa_slave_to_port(dev);
1335 struct dsa_slave_priv *p = netdev_priv(dev);
1336 struct dsa_switch *ds = p->dp->ds;
1337 struct dsa_port *cpu_dp;
1338 int port = p->dp->index;

--- 60 unchanged lines hidden (view full) ---

1399 }
1400
1401 err = dsa_port_mtu_change(dp, new_mtu, false);
1402 if (err)
1403 goto out_port_failed;
1404
1405 dev->mtu = new_mtu;
1406
1407 dsa_bridge_mtu_normalization(dp);
1408
1297 return 0;
1298
1299out_port_failed:
1300 if (new_master_mtu != old_master_mtu)
1301 dsa_port_mtu_change(cpu_dp, old_master_mtu -
1302 cpu_dp->tag_ops->overhead,
1303 true);
1304out_cpu_failed:

--- 338 unchanged lines hidden (view full) ---

1643 struct netdev_notifier_changeupper_info *info)
1644{
1645 struct dsa_port *dp = dsa_slave_to_port(dev);
1646 int err = NOTIFY_DONE;
1647
1648 if (netif_is_bridge_master(info->upper_dev)) {
1649 if (info->linking) {
1650 err = dsa_port_bridge_join(dp, info->upper_dev);
1409 return 0;
1410
1411out_port_failed:
1412 if (new_master_mtu != old_master_mtu)
1413 dsa_port_mtu_change(cpu_dp, old_master_mtu -
1414 cpu_dp->tag_ops->overhead,
1415 true);
1416out_cpu_failed:

--- 338 unchanged lines hidden (view full) ---

1755 struct netdev_notifier_changeupper_info *info)
1756{
1757 struct dsa_port *dp = dsa_slave_to_port(dev);
1758 int err = NOTIFY_DONE;
1759
1760 if (netif_is_bridge_master(info->upper_dev)) {
1761 if (info->linking) {
1762 err = dsa_port_bridge_join(dp, info->upper_dev);
1763 if (!err)
1764 dsa_bridge_mtu_normalization(dp);
1651 err = notifier_from_errno(err);
1652 } else {
1653 dsa_port_bridge_leave(dp, info->upper_dev);
1654 err = NOTIFY_OK;
1655 }
1656 }
1657
1658 return err;

--- 248 unchanged lines hidden ---
1765 err = notifier_from_errno(err);
1766 } else {
1767 dsa_port_bridge_leave(dp, info->upper_dev);
1768 err = NOTIFY_OK;
1769 }
1770 }
1771
1772 return err;

--- 248 unchanged lines hidden ---