kernel: copy kernel 4.19 code to 5.4
[oweals/openwrt.git] / target / linux / generic / backport-5.4 / 710-v5.3-net-phy-allow-Clause-45-access-via-mii-ioctl.patch
1 From eb5df3d026824832831376bbdf04e01a52776eea Mon Sep 17 00:00:00 2001
2 From: Russell King <rmk+kernel@armlinux.org.uk>
3 Date: Tue, 28 May 2019 10:57:29 +0100
4 Subject: [PATCH 608/660] net: phy: allow Clause 45 access via mii ioctl
5
6 Allow userspace to generate Clause 45 MII access cycles via phylib.
7 This is useful for tools such as mii-diag to be able to inspect Clause
8 45 PHYs.
9
10 Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
11 Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
12 Signed-off-by: David S. Miller <davem@davemloft.net>
13 Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
14 ---
15  drivers/net/phy/phy.c | 33 ++++++++++++++++++++++++---------
16  1 file changed, 24 insertions(+), 9 deletions(-)
17
18 --- a/drivers/net/phy/phy.c
19 +++ b/drivers/net/phy/phy.c
20 @@ -397,6 +397,7 @@ int phy_mii_ioctl(struct phy_device *phy
21         struct mii_ioctl_data *mii_data = if_mii(ifr);
22         u16 val = mii_data->val_in;
23         bool change_autoneg = false;
24 +       int prtad, devad;
25  
26         switch (cmd) {
27         case SIOCGMIIPHY:
28 @@ -404,14 +405,29 @@ int phy_mii_ioctl(struct phy_device *phy
29                 /* fall through */
30  
31         case SIOCGMIIREG:
32 -               mii_data->val_out = mdiobus_read(phydev->mdio.bus,
33 -                                                mii_data->phy_id,
34 -                                                mii_data->reg_num);
35 +               if (mdio_phy_id_is_c45(mii_data->phy_id)) {
36 +                       prtad = mdio_phy_id_prtad(mii_data->phy_id);
37 +                       devad = mdio_phy_id_devad(mii_data->phy_id);
38 +                       devad = MII_ADDR_C45 | devad << 16 | mii_data->reg_num;
39 +               } else {
40 +                       prtad = mii_data->phy_id;
41 +                       devad = mii_data->reg_num;
42 +               }
43 +               mii_data->val_out = mdiobus_read(phydev->mdio.bus, prtad,
44 +                                                devad);
45                 return 0;
46  
47         case SIOCSMIIREG:
48 -               if (mii_data->phy_id == phydev->mdio.addr) {
49 -                       switch (mii_data->reg_num) {
50 +               if (mdio_phy_id_is_c45(mii_data->phy_id)) {
51 +                       prtad = mdio_phy_id_prtad(mii_data->phy_id);
52 +                       devad = mdio_phy_id_devad(mii_data->phy_id);
53 +                       devad = MII_ADDR_C45 | devad << 16 | mii_data->reg_num;
54 +               } else {
55 +                       prtad = mii_data->phy_id;
56 +                       devad = mii_data->reg_num;
57 +               }
58 +               if (prtad == phydev->mdio.addr) {
59 +                       switch (devad) {
60                         case MII_BMCR:
61                                 if ((val & (BMCR_RESET | BMCR_ANENABLE)) == 0) {
62                                         if (phydev->autoneg == AUTONEG_ENABLE)
63 @@ -443,11 +459,10 @@ int phy_mii_ioctl(struct phy_device *phy
64                         }
65                 }
66  
67 -               mdiobus_write(phydev->mdio.bus, mii_data->phy_id,
68 -                             mii_data->reg_num, val);
69 +               mdiobus_write(phydev->mdio.bus, prtad, devad, val);
70  
71 -               if (mii_data->phy_id == phydev->mdio.addr &&
72 -                   mii_data->reg_num == MII_BMCR &&
73 +               if (prtad == phydev->mdio.addr &&
74 +                   devad == MII_BMCR &&
75                     val & BMCR_RESET)
76                         return phy_init_hw(phydev);
77