kernel: generic: Add kernel 4.14 support
[openwrt/openwrt.git] / target / linux / generic / pending-4.14 / 701-phy_extension.patch
1 From: John Crispin <john@phrozen.org>
2 Subject: net: phy: add phy_ethtool_ioctl()
3
4 Signed-off-by: John Crispin <john@phrozen.org>
5 ---
6 drivers/net/phy/phy.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
7 include/linux/phy.h | 1 +
8 2 files changed, 45 insertions(+)
9
10 --- a/drivers/net/phy/phy.c
11 +++ b/drivers/net/phy/phy.c
12 @@ -382,6 +382,73 @@ void phy_ethtool_ksettings_get(struct ph
13 }
14 EXPORT_SYMBOL(phy_ethtool_ksettings_get);
15
16 +static int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd)
17 +{
18 + cmd->supported = phydev->supported;
19 +
20 + cmd->advertising = phydev->advertising;
21 + cmd->lp_advertising = phydev->lp_advertising;
22 +
23 + ethtool_cmd_speed_set(cmd, phydev->speed);
24 + cmd->duplex = phydev->duplex;
25 + if (phydev->interface == PHY_INTERFACE_MODE_MOCA)
26 + cmd->port = PORT_BNC;
27 + else
28 + cmd->port = PORT_MII;
29 + cmd->phy_address = phydev->mdio.addr;
30 + cmd->transceiver = phy_is_internal(phydev) ?
31 + XCVR_INTERNAL : XCVR_EXTERNAL;
32 + cmd->autoneg = phydev->autoneg;
33 + cmd->eth_tp_mdix_ctrl = phydev->mdix_ctrl;
34 + cmd->eth_tp_mdix = phydev->mdix;
35 +
36 + return 0;
37 +}
38 +
39 +int phy_ethtool_ioctl(struct phy_device *phydev, void *useraddr)
40 +{
41 + u32 cmd;
42 + int tmp;
43 + struct ethtool_cmd ecmd = { ETHTOOL_GSET };
44 + struct ethtool_value edata = { ETHTOOL_GLINK };
45 +
46 + if (get_user(cmd, (u32 *) useraddr))
47 + return -EFAULT;
48 +
49 + switch (cmd) {
50 + case ETHTOOL_GSET:
51 + phy_ethtool_gset(phydev, &ecmd);
52 + if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
53 + return -EFAULT;
54 + return 0;
55 +
56 + case ETHTOOL_SSET:
57 + if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
58 + return -EFAULT;
59 + return phy_ethtool_sset(phydev, &ecmd);
60 +
61 + case ETHTOOL_NWAY_RST:
62 + /* if autoneg is off, it's an error */
63 + tmp = phy_read(phydev, MII_BMCR);
64 + if (tmp & BMCR_ANENABLE) {
65 + tmp |= (BMCR_ANRESTART);
66 + phy_write(phydev, MII_BMCR, tmp);
67 + return 0;
68 + }
69 + return -EINVAL;
70 +
71 + case ETHTOOL_GLINK:
72 + edata.data = (phy_read(phydev,
73 + MII_BMSR) & BMSR_LSTATUS) ? 1 : 0;
74 + if (copy_to_user(useraddr, &edata, sizeof(edata)))
75 + return -EFAULT;
76 + return 0;
77 + }
78 +
79 + return -EOPNOTSUPP;
80 +}
81 +EXPORT_SYMBOL(phy_ethtool_ioctl);
82 +
83 /**
84 * phy_mii_ioctl - generic PHY MII ioctl interface
85 * @phydev: the phy_device struct
86 --- a/include/linux/phy.h
87 +++ b/include/linux/phy.h
88 @@ -905,6 +905,7 @@ void phy_ethtool_ksettings_get(struct ph
89 struct ethtool_link_ksettings *cmd);
90 int phy_ethtool_ksettings_set(struct phy_device *phydev,
91 const struct ethtool_link_ksettings *cmd);
92 +int phy_ethtool_ioctl(struct phy_device *phydev, void *useraddr);
93 int phy_mii_ioctl(struct phy_device *phydev, struct ifreq *ifr, int cmd);
94 int phy_start_interrupts(struct phy_device *phydev);
95 void phy_print_status(struct phy_device *phydev);