Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0015b80a authored by Salvatore Mesoraca's avatar Salvatore Mesoraca Committed by David S. Miller
Browse files

net: dsa: Remove VLA usage

We avoid 2 VLAs by using a pre-allocated field in dsa_switch. We also
try to avoid dynamic allocation whenever possible (when using fewer than
bits-per-long ports, which is the common case).

Link: http://lkml.kernel.org/r/CA+55aFzCG-zNmZwX4A2FQpadafLfEzK6CC=qPXydAacU1RqZWA@mail.gmail.com
Link: http://lkml.kernel.org/r/20180505185145.GB32630@lunn.ch


Signed-off-by: default avatarSalvatore Mesoraca <s.mesoraca16@gmail.com>
[kees: tweak commit subject and message slightly]
Signed-off-by: default avatarKees Cook <keescook@chromium.org>
Reviewed-by: default avatarAndrew Lunn <andrew@lunn.ch>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 14260e91
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -259,6 +259,9 @@ struct dsa_switch {
	/* Number of switch port queues */
	unsigned int		num_tx_queues;

	unsigned long		*bitmap;
	unsigned long		_bitmap;

	/* Dynamically allocated ports, keep last */
	size_t num_ports;
	struct dsa_port ports[];
+14 −0
Original line number Diff line number Diff line
@@ -775,6 +775,20 @@ struct dsa_switch *dsa_switch_alloc(struct device *dev, size_t n)
	if (!ds)
		return NULL;

	/* We avoid allocating memory outside dsa_switch
	 * if it is not needed.
	 */
	if (n <= sizeof(ds->_bitmap) * 8) {
		ds->bitmap = &ds->_bitmap;
	} else {
		ds->bitmap = devm_kcalloc(dev,
					  BITS_TO_LONGS(n),
					  sizeof(unsigned long),
					  GFP_KERNEL);
		if (unlikely(!ds->bitmap))
			return NULL;
	}

	ds->dev = dev;
	ds->num_ports = n;

+10 −12
Original line number Diff line number Diff line
@@ -136,21 +136,20 @@ static int dsa_switch_mdb_add(struct dsa_switch *ds,
{
	const struct switchdev_obj_port_mdb *mdb = info->mdb;
	struct switchdev_trans *trans = info->trans;
	DECLARE_BITMAP(group, ds->num_ports);
	int port;

	/* Build a mask of Multicast group members */
	bitmap_zero(group, ds->num_ports);
	bitmap_zero(ds->bitmap, ds->num_ports);
	if (ds->index == info->sw_index)
		set_bit(info->port, group);
		set_bit(info->port, ds->bitmap);
	for (port = 0; port < ds->num_ports; port++)
		if (dsa_is_dsa_port(ds, port))
			set_bit(port, group);
			set_bit(port, ds->bitmap);

	if (switchdev_trans_ph_prepare(trans))
		return dsa_switch_mdb_prepare_bitmap(ds, mdb, group);
		return dsa_switch_mdb_prepare_bitmap(ds, mdb, ds->bitmap);

	dsa_switch_mdb_add_bitmap(ds, mdb, group);
	dsa_switch_mdb_add_bitmap(ds, mdb, ds->bitmap);

	return 0;
}
@@ -204,21 +203,20 @@ static int dsa_switch_vlan_add(struct dsa_switch *ds,
{
	const struct switchdev_obj_port_vlan *vlan = info->vlan;
	struct switchdev_trans *trans = info->trans;
	DECLARE_BITMAP(members, ds->num_ports);
	int port;

	/* Build a mask of VLAN members */
	bitmap_zero(members, ds->num_ports);
	bitmap_zero(ds->bitmap, ds->num_ports);
	if (ds->index == info->sw_index)
		set_bit(info->port, members);
		set_bit(info->port, ds->bitmap);
	for (port = 0; port < ds->num_ports; port++)
		if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port))
			set_bit(port, members);
			set_bit(port, ds->bitmap);

	if (switchdev_trans_ph_prepare(trans))
		return dsa_switch_vlan_prepare_bitmap(ds, vlan, members);
		return dsa_switch_vlan_prepare_bitmap(ds, vlan, ds->bitmap);

	dsa_switch_vlan_add_bitmap(ds, vlan, members);
	dsa_switch_vlan_add_bitmap(ds, vlan, ds->bitmap);

	return 0;
}