generic: 6.1: backport various qca8k fixes patch
[openwrt/openwrt.git] / target / linux / generic / backport-6.1 / 779-v6.5-net-dsa-qca8k-enable-use_single_write-for-qca8xxx.patch
1 From 2c39dd025da489cf87d26469d9f5ff19715324a0 Mon Sep 17 00:00:00 2001
2 From: Christian Marangi <ansuelsmth@gmail.com>
3 Date: Mon, 24 Jul 2023 05:25:28 +0200
4 Subject: [PATCH 1/4] net: dsa: qca8k: enable use_single_write for qca8xxx
5
6 The qca8xxx switch supports 2 way to write reg values, a slow way using
7 mdio and a fast way by sending specially crafted mgmt packet to
8 read/write reg.
9
10 The fast way can support up to 32 bytes of data as eth packet are used
11 to send/receive.
12
13 This correctly works for almost the entire regmap of the switch but with
14 the use of some kernel selftests for dsa drivers it was found a funny
15 and interesting hw defect/limitation.
16
17 For some specific reg, bulk write won't work and will result in writing
18 only part of the requested regs resulting in half data written. This was
19 especially hard to track and discover due to the total strangeness of
20 the problem and also by the specific regs where this occurs.
21
22 This occurs in the specific regs of the ATU table, where multiple entry
23 needs to be written to compose the entire entry.
24 It was discovered that with a bulk write of 12 bytes on
25 QCA8K_REG_ATU_DATA0 only QCA8K_REG_ATU_DATA0 and QCA8K_REG_ATU_DATA2
26 were written, but QCA8K_REG_ATU_DATA1 was always zero.
27 Tcpdump was used to make sure the specially crafted packet was correct
28 and this was confirmed.
29
30 The problem was hard to track as the lack of QCA8K_REG_ATU_DATA1
31 resulted in an entry somehow possible as the first bytes of the mac
32 address are set in QCA8K_REG_ATU_DATA0 and the entry type is set in
33 QCA8K_REG_ATU_DATA2.
34
35 Funlly enough writing QCA8K_REG_ATU_DATA1 results in the same problem
36 with QCA8K_REG_ATU_DATA2 empty and QCA8K_REG_ATU_DATA1 and
37 QCA8K_REG_ATU_FUNC correctly written.
38 A speculation on the problem might be that there are some kind of
39 indirection internally when accessing these regs and they can't be
40 accessed all together, due to the fact that it's really a table mapped
41 somewhere in the switch SRAM.
42
43 Even more funny is the fact that every other reg was tested with all
44 kind of combination and they are not affected by this problem. Read
45 operation was also tested and always worked so it's not affected by this
46 problem.
47
48 The problem is not present if we limit writing a single reg at times.
49
50 To handle this hardware defect, enable use_single_write so that bulk
51 api can correctly split the write in multiple different operation
52 effectively reverting to a non-bulk write.
53
54 Cc: Mark Brown <broonie@kernel.org>
55 Fixes: c766e077d927 ("net: dsa: qca8k: convert to regmap read/write API")
56 Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
57 Cc: stable@vger.kernel.org
58 Signed-off-by: David S. Miller <davem@davemloft.net>
59 ---
60 drivers/net/dsa/qca/qca8k-8xxx.c | 7 +++++--
61 1 file changed, 5 insertions(+), 2 deletions(-)
62
63 --- a/drivers/net/dsa/qca/qca8k-8xxx.c
64 +++ b/drivers/net/dsa/qca/qca8k-8xxx.c
65 @@ -575,8 +575,11 @@ static struct regmap_config qca8k_regmap
66 .rd_table = &qca8k_readable_table,
67 .disable_locking = true, /* Locking is handled by qca8k read/write */
68 .cache_type = REGCACHE_NONE, /* Explicitly disable CACHE */
69 - .max_raw_read = 32, /* mgmt eth can read/write up to 8 registers at time */
70 - .max_raw_write = 32,
71 + .max_raw_read = 32, /* mgmt eth can read up to 8 registers at time */
72 + /* ATU regs suffer from a bug where some data are not correctly
73 + * written. Disable bulk write to correctly write ATU entry.
74 + */
75 + .use_single_write = true,
76 };
77
78 static int