Commit 41378cfd authored by Sam Edwards's avatar Sam Edwards Committed by Jakub Kicinski
Browse files

net: dsa: bcm_sf2: fix crossbar port bitwidth logic



The SF2 crossbar register is a packed bitfield, giving the index of the
external port selected for each of the internal ports. On BCM4908 (the
only currently-supported switch family with a crossbar), there are 2
internal ports and 3 external ports, so there are 2 bits per internal
port.

The driver currently conflates the "bits per port" and "number of ports"
concepts, lumping both into the `num_crossbar_int_ports` field. Since it
is currently only possible for either of these counts to have a value of
2, there is no behavioral error resulting from this situation for now.

Make the code more readable (and support the future possibility of
larger crossbars) by adding a `num_crossbar_ext_bits` field to represent
the "bits per port" count and relying on this where appropriate instead.

Signed-off-by: default avatarSam Edwards <CFSworks@gmail.com>
Reviewed-by: default avatarFlorian Fainelli <florian.fainelli@broadcom.com>
Link: https://patch.msgid.link/20241003212301.1339647-1-CFSworks@gmail.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 0da7fb3b
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -513,12 +513,12 @@ static void bcm_sf2_crossbar_setup(struct bcm_sf2_priv *priv)
	u32 reg;
	int i;

	mask = BIT(priv->num_crossbar_int_ports) - 1;
	mask = BIT(priv->num_crossbar_ext_bits) - 1;

	reg = reg_readl(priv, REG_CROSSBAR);
	switch (priv->type) {
	case BCM4908_DEVICE_ID:
		shift = CROSSBAR_BCM4908_INT_P7 * priv->num_crossbar_int_ports;
		shift = CROSSBAR_BCM4908_INT_P7 * priv->num_crossbar_ext_bits;
		reg &= ~(mask << shift);
		if (0) /* FIXME */
			reg |= CROSSBAR_BCM4908_EXT_SERDES << shift;
@@ -536,7 +536,7 @@ static void bcm_sf2_crossbar_setup(struct bcm_sf2_priv *priv)

	reg = reg_readl(priv, REG_CROSSBAR);
	for (i = 0; i < priv->num_crossbar_int_ports; i++) {
		shift = i * priv->num_crossbar_int_ports;
		shift = i * priv->num_crossbar_ext_bits;

		dev_dbg(dev, "crossbar int port #%d - ext port #%d\n", i,
			(reg >> shift) & mask);
@@ -1260,6 +1260,7 @@ struct bcm_sf2_of_data {
	unsigned int core_reg_align;
	unsigned int num_cfp_rules;
	unsigned int num_crossbar_int_ports;
	unsigned int num_crossbar_ext_bits;
};

static const u16 bcm_sf2_4908_reg_offsets[] = {
@@ -1288,6 +1289,7 @@ static const struct bcm_sf2_of_data bcm_sf2_4908_data = {
	.reg_offsets	= bcm_sf2_4908_reg_offsets,
	.num_cfp_rules	= 256,
	.num_crossbar_int_ports = 2,
	.num_crossbar_ext_bits = 2,
};

/* Register offsets for the SWITCH_REG_* block */
@@ -1399,6 +1401,7 @@ static int bcm_sf2_sw_probe(struct platform_device *pdev)
	priv->core_reg_align = data->core_reg_align;
	priv->num_cfp_rules = data->num_cfp_rules;
	priv->num_crossbar_int_ports = data->num_crossbar_int_ports;
	priv->num_crossbar_ext_bits = data->num_crossbar_ext_bits;

	priv->rcdev = devm_reset_control_get_optional_exclusive(&pdev->dev,
								"switch");
+1 −0
Original line number Diff line number Diff line
@@ -75,6 +75,7 @@ struct bcm_sf2_priv {
	unsigned int			core_reg_align;
	unsigned int			num_cfp_rules;
	unsigned int			num_crossbar_int_ports;
	unsigned int			num_crossbar_ext_bits;

	/* spinlock protecting access to the indirect registers */
	spinlock_t			indir_lock;