]> git.baikalelectronics.ru Git - kernel.git/commitdiff
net: dsa: sja1105: fix VL lookup command packing for P/Q/R/S
authorVladimir Oltean <vladimir.oltean@nxp.com>
Mon, 24 May 2021 09:25:22 +0000 (12:25 +0300)
committerDavid S. Miller <davem@davemloft.net>
Mon, 24 May 2021 20:20:24 +0000 (13:20 -0700)
At the beginning of the sja1105_dynamic_config.c file there is a diagram
of the dynamic config interface layout:

 packed_buf

 |
 V
 +-----------------------------------------+------------------+
 |              ENTRY BUFFER               |  COMMAND BUFFER  |
 +-----------------------------------------+------------------+

 <----------------------- packed_size ------------------------>

So in order to pack/unpack the command bits into the buffer,
sja1105_vl_lookup_cmd_packing must first advance the buffer pointer by
the length of the entry. This is similar to what the other *cmd_packing
functions do.

This bug exists because the command packing function for P/Q/R/S was
copied from the E/T generation, and on E/T, the command was actually
embedded within the entry buffer itself.

Fixes: 94f94d4acfb2 ("net: dsa: sja1105: add static tables for virtual links")
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/dsa/sja1105/sja1105_dynamic_config.c

index b777d3f375736e891f91fb6b54b838973e4aa4b6..12cd04b56803056e6c4e687d543f9ff872676664 100644 (file)
@@ -167,9 +167,10 @@ enum sja1105_hostcmd {
        SJA1105_HOSTCMD_INVALIDATE = 4,
 };
 
+/* Command and entry overlap */
 static void
-sja1105_vl_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
-                             enum packing_op op)
+sja1105et_vl_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
+                               enum packing_op op)
 {
        const int size = SJA1105_SIZE_DYN_CMD;
 
@@ -179,6 +180,20 @@ sja1105_vl_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
        sja1105_packing(buf, &cmd->index,    9,  0, size, op);
 }
 
+/* Command and entry are separate */
+static void
+sja1105pqrs_vl_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
+                                 enum packing_op op)
+{
+       u8 *p = buf + SJA1105_SIZE_VL_LOOKUP_ENTRY;
+       const int size = SJA1105_SIZE_DYN_CMD;
+
+       sja1105_packing(p, &cmd->valid,   31, 31, size, op);
+       sja1105_packing(p, &cmd->errors,  30, 30, size, op);
+       sja1105_packing(p, &cmd->rdwrset, 29, 29, size, op);
+       sja1105_packing(p, &cmd->index,    9,  0, size, op);
+}
+
 static size_t sja1105et_vl_lookup_entry_packing(void *buf, void *entry_ptr,
                                                enum packing_op op)
 {
@@ -641,7 +656,7 @@ static size_t sja1105pqrs_cbs_entry_packing(void *buf, void *entry_ptr,
 const struct sja1105_dynamic_table_ops sja1105et_dyn_ops[BLK_IDX_MAX_DYN] = {
        [BLK_IDX_VL_LOOKUP] = {
                .entry_packing = sja1105et_vl_lookup_entry_packing,
-               .cmd_packing = sja1105_vl_lookup_cmd_packing,
+               .cmd_packing = sja1105et_vl_lookup_cmd_packing,
                .access = OP_WRITE,
                .max_entry_count = SJA1105_MAX_VL_LOOKUP_COUNT,
                .packed_size = SJA1105ET_SIZE_VL_LOOKUP_DYN_CMD,
@@ -725,7 +740,7 @@ const struct sja1105_dynamic_table_ops sja1105et_dyn_ops[BLK_IDX_MAX_DYN] = {
 const struct sja1105_dynamic_table_ops sja1105pqrs_dyn_ops[BLK_IDX_MAX_DYN] = {
        [BLK_IDX_VL_LOOKUP] = {
                .entry_packing = sja1105_vl_lookup_entry_packing,
-               .cmd_packing = sja1105_vl_lookup_cmd_packing,
+               .cmd_packing = sja1105pqrs_vl_lookup_cmd_packing,
                .access = (OP_READ | OP_WRITE),
                .max_entry_count = SJA1105_MAX_VL_LOOKUP_COUNT,
                .packed_size = SJA1105PQRS_SIZE_VL_LOOKUP_DYN_CMD,