d32a7edf93cdcba9b6931d46911f2fece1952637
[openwrt/staging/pepe2k.git] /
1 From 7edce370d87a23e8ed46af5b76a9fef1e341b67b Mon Sep 17 00:00:00 2001
2 From: Christian Marangi <ansuelsmth@gmail.com>
3 Date: Tue, 28 Nov 2023 14:59:28 +0100
4 Subject: [PATCH] net: phy: aquantia: drop wrong endianness conversion for addr
5 and CRC
6
7 On further testing on BE target with kernel test robot, it was notice
8 that the endianness conversion for addr and CRC in fw_load_memory was
9 wrong.
10
11 Drop the cpu_to_le32 conversion for addr load as it's not needed.
12
13 Use get_unaligned_le32 instead of get_unaligned for FW data word load to
14 correctly convert data in the correct order to follow system endian.
15
16 Also drop the cpu_to_be32 for CRC calculation as it's wrong and would
17 cause different CRC on BE system.
18 The loaded word is swapped internally and MAILBOX calculates the CRC on
19 the swapped word. To correctly calculate the CRC to be later matched
20 with the one from MAILBOX, use an u8 struct and swap the word there to
21 keep the same order on both LE and BE for crc_ccitt_false function.
22 Also add additional comments on how the CRC verification for the loaded
23 section works.
24
25 CRC is calculated as we load the section and verified with the MAILBOX
26 only after the entire section is loaded to skip additional slowdown by
27 loop the section data again.
28
29 Reported-by: kernel test robot <lkp@intel.com>
30 Closes: https://lore.kernel.org/oe-kbuild-all/202311210414.sEJZjlcD-lkp@intel.com/
31 Fixes: e93984ebc1c8 ("net: phy: aquantia: add firmware load support")
32 Tested-by: Robert Marko <robimarko@gmail.com> # ipq8072 LE device
33 Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
34 Link: https://lore.kernel.org/r/20231128135928.9841-1-ansuelsmth@gmail.com
35 Signed-off-by: Jakub Kicinski <kuba@kernel.org>
36 ---
37 drivers/net/phy/aquantia/aquantia_firmware.c | 24 ++++++++++++--------
38 1 file changed, 14 insertions(+), 10 deletions(-)
39
40 --- a/drivers/net/phy/aquantia/aquantia_firmware.c
41 +++ b/drivers/net/phy/aquantia/aquantia_firmware.c
42 @@ -93,9 +93,6 @@ static int aqr_fw_load_memory(struct phy
43 u16 crc = 0, up_crc;
44 size_t pos;
45
46 - /* PHY expect addr in LE */
47 - addr = (__force u32)cpu_to_le32(addr);
48 -
49 phy_write_mmd(phydev, MDIO_MMD_VEND1,
50 VEND1_GLOBAL_MAILBOX_INTERFACE1,
51 VEND1_GLOBAL_MAILBOX_INTERFACE1_CRC_RESET);
52 @@ -110,10 +107,11 @@ static int aqr_fw_load_memory(struct phy
53 * If a firmware that is not word aligned is found, please report upstream.
54 */
55 for (pos = 0; pos < len; pos += sizeof(u32)) {
56 + u8 crc_data[4];
57 u32 word;
58
59 /* FW data is always stored in little-endian */
60 - word = get_unaligned((const u32 *)(data + pos));
61 + word = get_unaligned_le32((const u32 *)(data + pos));
62
63 phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_MAILBOX_INTERFACE5,
64 VEND1_GLOBAL_MAILBOX_INTERFACE5_MSW_DATA(word));
65 @@ -124,15 +122,21 @@ static int aqr_fw_load_memory(struct phy
66 VEND1_GLOBAL_MAILBOX_INTERFACE1_EXECUTE |
67 VEND1_GLOBAL_MAILBOX_INTERFACE1_WRITE);
68
69 - /* calculate CRC as we load data to the mailbox.
70 - * We convert word to big-endian as PHY is BE and mailbox will
71 - * return a BE CRC.
72 + /* Word is swapped internally and MAILBOX CRC is calculated
73 + * using big-endian order. Mimic what the PHY does to have a
74 + * matching CRC...
75 */
76 - word = (__force u32)cpu_to_be32(word);
77 - crc = crc_ccitt_false(crc, (u8 *)&word, sizeof(word));
78 - }
79 + crc_data[0] = word >> 24;
80 + crc_data[1] = word >> 16;
81 + crc_data[2] = word >> 8;
82 + crc_data[3] = word;
83
84 + /* ...calculate CRC as we load data... */
85 + crc = crc_ccitt_false(crc, crc_data, sizeof(crc_data));
86 + }
87 + /* ...gets CRC from MAILBOX after we have loaded the entire section... */
88 up_crc = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_MAILBOX_INTERFACE2);
89 + /* ...and make sure it does match our calculated CRC */
90 if (crc != up_crc) {
91 phydev_err(phydev, "CRC mismatch: calculated 0x%04x PHY 0x%04x\n",
92 crc, up_crc);