void (*get_strings)(struct phy_device *dev, u8 *data);
        void (*get_stats)(struct phy_device *dev,
                          struct ethtool_stats *stats, u64 *data);
+
+       /* Get and Set PHY tunables */
+       int (*get_tunable)(struct phy_device *dev,
+                          struct ethtool_tunable *tuna, void *data);
+       int (*set_tunable)(struct phy_device *dev,
+                           struct ethtool_tunable *tuna,
+                           const void *data);
 };
 #define to_phy_driver(d) container_of(to_mdio_common_driver(d),                \
                                      struct phy_driver, mdiodrv)
 
        [ETHTOOL_TX_COPYBREAK]  = "tx-copybreak",
 };
 
+static const char
+phy_tunable_strings[__ETHTOOL_PHY_TUNABLE_COUNT][ETH_GSTRING_LEN] = {
+       [ETHTOOL_ID_UNSPEC]     = "Unspec",
+};
+
 static int ethtool_get_features(struct net_device *dev, void __user *useraddr)
 {
        struct ethtool_gfeatures cmd = {
        if (sset == ETH_SS_TUNABLES)
                return ARRAY_SIZE(tunable_strings);
 
+       if (sset == ETH_SS_PHY_TUNABLES)
+               return ARRAY_SIZE(phy_tunable_strings);
+
        if (sset == ETH_SS_PHY_STATS) {
                if (dev->phydev)
                        return phy_get_sset_count(dev->phydev);
                       sizeof(rss_hash_func_strings));
        else if (stringset == ETH_SS_TUNABLES)
                memcpy(data, tunable_strings, sizeof(tunable_strings));
+       else if (stringset == ETH_SS_PHY_TUNABLES)
+               memcpy(data, phy_tunable_strings, sizeof(phy_tunable_strings));
        else if (stringset == ETH_SS_PHY_STATS) {
                struct phy_device *phydev = dev->phydev;
 
        };
 }
 
+static int ethtool_phy_tunable_valid(const struct ethtool_tunable *tuna)
+{
+       switch (tuna->id) {
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int get_phy_tunable(struct net_device *dev, void __user *useraddr)
+{
+       int ret;
+       struct ethtool_tunable tuna;
+       struct phy_device *phydev = dev->phydev;
+       void *data;
+
+       if (!(phydev && phydev->drv && phydev->drv->get_tunable))
+               return -EOPNOTSUPP;
+
+       if (copy_from_user(&tuna, useraddr, sizeof(tuna)))
+               return -EFAULT;
+       ret = ethtool_phy_tunable_valid(&tuna);
+       if (ret)
+               return ret;
+       data = kmalloc(tuna.len, GFP_USER);
+       if (!data)
+               return -ENOMEM;
+       ret = phydev->drv->get_tunable(phydev, &tuna, data);
+       if (ret)
+               goto out;
+       useraddr += sizeof(tuna);
+       ret = -EFAULT;
+       if (copy_to_user(useraddr, data, tuna.len))
+               goto out;
+       ret = 0;
+
+out:
+       kfree(data);
+       return ret;
+}
+
+static int set_phy_tunable(struct net_device *dev, void __user *useraddr)
+{
+       int ret;
+       struct ethtool_tunable tuna;
+       struct phy_device *phydev = dev->phydev;
+       void *data;
+
+       if (!(phydev && phydev->drv && phydev->drv->set_tunable))
+               return -EOPNOTSUPP;
+       if (copy_from_user(&tuna, useraddr, sizeof(tuna)))
+               return -EFAULT;
+       ret = ethtool_phy_tunable_valid(&tuna);
+       if (ret)
+               return ret;
+       data = kmalloc(tuna.len, GFP_USER);
+       if (!data)
+               return -ENOMEM;
+       useraddr += sizeof(tuna);
+       ret = -EFAULT;
+       if (copy_from_user(data, useraddr, tuna.len))
+               goto out;
+       ret = phydev->drv->set_tunable(phydev, &tuna, data);
+
+out:
+       kfree(data);
+       return ret;
+}
+
 /* The main entry point in this file.  Called from net/core/dev_ioctl.c */
 
 int dev_ethtool(struct net *net, struct ifreq *ifr)
        case ETHTOOL_GET_TS_INFO:
        case ETHTOOL_GEEE:
        case ETHTOOL_GTUNABLE:
+       case ETHTOOL_PHY_GTUNABLE:
                break;
        default:
                if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
        case ETHTOOL_SLINKSETTINGS:
                rc = ethtool_set_link_ksettings(dev, useraddr);
                break;
+       case ETHTOOL_PHY_GTUNABLE:
+               rc = get_phy_tunable(dev, useraddr);
+               break;
+       case ETHTOOL_PHY_STUNABLE:
+               rc = set_phy_tunable(dev, useraddr);
+               break;
        default:
                rc = -EOPNOTSUPP;
        }