]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
net: dsa: bcm_sf2: fix crossbar port bitwidth logic
authorSam Edwards <cfsworks@gmail.com>
Thu, 3 Oct 2024 21:23:01 +0000 (14:23 -0700)
committerJakub Kicinski <kuba@kernel.org>
Fri, 4 Oct 2024 23:16:15 +0000 (16:16 -0700)
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: Sam Edwards <CFSworks@gmail.com>
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
Link: https://patch.msgid.link/20241003212301.1339647-1-CFSworks@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/dsa/bcm_sf2.c
drivers/net/dsa/bcm_sf2.h

index 0e663ec0c12a3bcbd865f29b13596dae3b6a6a30..3ae794a30acee9e65758f8607915ed409870ac79 100644 (file)
@@ -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");
index f95f4880b69e178b644b0d5269b3e7e13e8cdb7f..4fda075a34492755d3f56e81f3dfb3d5cdb5ca94 100644 (file)
@@ -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;