kernel: copy kernel 4.19 code to 5.4
[openwrt/openwrt.git] / target / linux / generic / backport-5.4 / 740-v5.5-net-phy-avoid-matching-all-ones-clause-45-PHY-IDs.patch
1 From 1be8018db381200c24854e0c299206c557f76fe0 Mon Sep 17 00:00:00 2001
2 From: Russell King <rmk+kernel@armlinux.org.uk>
3 Date: Mon, 11 Nov 2019 11:58:09 +0000
4 Subject: [PATCH 638/660] net: phy: avoid matching all-ones clause 45 PHY IDs
5
6 We currently match clause 45 PHYs using any ID read from a MMD marked
7 as present in the "Devices in package" registers 5 and 6. However,
8 this is incorrect. 45.2 says:
9
10 "The definition of the term package is vendor specific and could be
11 a chip, module, or other similar entity."
12
13 so a package could be more or less than the whole PHY - a PHY could be
14 made up of several modules instantiated onto a single chip such as the
15 Marvell 88x3310, or some of the MMDs could be disabled according to
16 chip configuration, such as the Broadcom 84881.
17
18 In the case of Broadcom 84881, the "Devices in package" registers
19 contain 0xc000009b, meaning that there is a PHYXS present in the
20 package, but all registers in MMD 4 return 0xffff. This leads to our
21 matching code incorrectly binding this PHY to one of our generic PHY
22 drivers.
23
24 This patch changes the way we determine whether to attempt to match a
25 MMD identifier, or use it to request a module - if the identifier is
26 all-ones, then we skip over it. When reading the identifiers, we
27 initialise phydev->c45_ids.device_ids to all-ones, only reading the
28 device ID if the "Devices in package" registers indicates we should.
29
30 This avoids the generic drivers incorrectly matching on a PHY ID of
31 0xffffffff.
32
33 Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
34 ---
35 drivers/net/phy/phy_device.c | 7 +++++--
36 1 file changed, 5 insertions(+), 2 deletions(-)
37
38 --- a/drivers/net/phy/phy_device.c
39 +++ b/drivers/net/phy/phy_device.c
40 @@ -335,7 +335,7 @@ static int phy_bus_match(struct device *
41
42 if (phydev->is_c45) {
43 for (i = 1; i < num_ids; i++) {
44 - if (!(phydev->c45_ids.devices_in_package & (1 << i)))
45 + if (phydev->c45_ids.device_ids[i] == 0xffffffff)
46 continue;
47
48 if ((phydrv->phy_id & phydrv->phy_id_mask) ==
49 @@ -623,10 +623,13 @@ static int get_phy_id(struct mii_bus *bu
50 */
51 struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45)
52 {
53 - struct phy_c45_device_ids c45_ids = {0};
54 + struct phy_c45_device_ids c45_ids;
55 u32 phy_id = 0;
56 int r;
57
58 + c45_ids.devices_in_package = 0;
59 + memset(c45_ids.device_ids, 0xff, sizeof(c45_ids.device_ids));
60 +
61 r = get_phy_id(bus, addr, &phy_id, is_c45, &c45_ids);
62 if (r)
63 return ERR_PTR(r);