Commit 9aedc6e2f1c6708120b80748556fb6ad0567d15d

Authored by Cris Forno
Committed by David S. Miller
1 parent 70ae1e127b

net/ethtool: Introduce link_ksettings API for virtual network devices

With the ethtool_virtdev_set_link_ksettings function in core/ethtool.c,
ibmveth, netvsc, and virtio now use the core's helper function.

Funtionality changes that pertain to ibmveth driver include:

  1. Changed the initial hardcoded link speed to 1GB.

  2. Added support for allowing a user to change the reported link
  speed via ethtool.

Functionality changes to the netvsc driver include:

  1. When netvsc_get_link_ksettings is called, it will defer to the VF
  device if it exists to pull accelerated networking values, otherwise
  pull default or user-defined values.

  2. Similarly, if netvsc_set_link_ksettings called and a VF device
  exists, the real values of speed and duplex are changed.

Signed-off-by: Cris Forno <cforno12@linux.vnet.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 4 changed files with 53 additions and 87 deletions Side-by-side Diff

drivers/net/ethernet/ibm/ibmveth.c
... ... @@ -712,29 +712,36 @@
712 712 return 0;
713 713 }
714 714  
715   -static int netdev_get_link_ksettings(struct net_device *dev,
716   - struct ethtool_link_ksettings *cmd)
  715 +static int ibmveth_set_link_ksettings(struct net_device *dev,
  716 + const struct ethtool_link_ksettings *cmd)
717 717 {
718   - u32 supported, advertising;
  718 + struct ibmveth_adapter *adapter = netdev_priv(dev);
719 719  
720   - supported = (SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg |
721   - SUPPORTED_FIBRE);
722   - advertising = (ADVERTISED_1000baseT_Full | ADVERTISED_Autoneg |
723   - ADVERTISED_FIBRE);
724   - cmd->base.speed = SPEED_1000;
725   - cmd->base.duplex = DUPLEX_FULL;
726   - cmd->base.port = PORT_FIBRE;
727   - cmd->base.phy_address = 0;
728   - cmd->base.autoneg = AUTONEG_ENABLE;
  720 + return ethtool_virtdev_set_link_ksettings(dev, cmd,
  721 + &adapter->speed,
  722 + &adapter->duplex);
  723 +}
729 724  
730   - ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
731   - supported);
732   - ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
733   - advertising);
  725 +static int ibmveth_get_link_ksettings(struct net_device *dev,
  726 + struct ethtool_link_ksettings *cmd)
  727 +{
  728 + struct ibmveth_adapter *adapter = netdev_priv(dev);
734 729  
  730 + cmd->base.speed = adapter->speed;
  731 + cmd->base.duplex = adapter->duplex;
  732 + cmd->base.port = PORT_OTHER;
  733 +
735 734 return 0;
736 735 }
737 736  
  737 +static void ibmveth_init_link_settings(struct net_device *dev)
  738 +{
  739 + struct ibmveth_adapter *adapter = netdev_priv(dev);
  740 +
  741 + adapter->speed = SPEED_1000;
  742 + adapter->duplex = DUPLEX_FULL;
  743 +}
  744 +
738 745 static void netdev_get_drvinfo(struct net_device *dev,
739 746 struct ethtool_drvinfo *info)
740 747 {
... ... @@ -965,12 +972,13 @@
965 972 }
966 973  
967 974 static const struct ethtool_ops netdev_ethtool_ops = {
968   - .get_drvinfo = netdev_get_drvinfo,
969   - .get_link = ethtool_op_get_link,
970   - .get_strings = ibmveth_get_strings,
971   - .get_sset_count = ibmveth_get_sset_count,
972   - .get_ethtool_stats = ibmveth_get_ethtool_stats,
973   - .get_link_ksettings = netdev_get_link_ksettings,
  975 + .get_drvinfo = netdev_get_drvinfo,
  976 + .get_link = ethtool_op_get_link,
  977 + .get_strings = ibmveth_get_strings,
  978 + .get_sset_count = ibmveth_get_sset_count,
  979 + .get_ethtool_stats = ibmveth_get_ethtool_stats,
  980 + .get_link_ksettings = ibmveth_get_link_ksettings,
  981 + .set_link_ksettings = ibmveth_set_link_ksettings,
974 982 };
975 983  
976 984 static int ibmveth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
... ... @@ -1674,6 +1682,7 @@
1674 1682 adapter->netdev = netdev;
1675 1683 adapter->mcastFilterSize = be32_to_cpu(*mcastFilterSize_p);
1676 1684 adapter->pool_config = 0;
  1685 + ibmveth_init_link_settings(netdev);
1677 1686  
1678 1687 netif_napi_add(netdev, &adapter->napi, ibmveth_poll, 16);
1679 1688  
drivers/net/ethernet/ibm/ibmveth.h
... ... @@ -162,6 +162,9 @@
162 162 u64 tx_send_failed;
163 163 u64 tx_large_packets;
164 164 u64 rx_large_packets;
  165 + /* Ethtool settings */
  166 + u8 duplex;
  167 + u32 speed;
165 168 };
166 169  
167 170 /*
drivers/net/hyperv/netvsc_drv.c
... ... @@ -1140,23 +1140,6 @@
1140 1140 return ret;
1141 1141 }
1142 1142  
1143   -static bool
1144   -netvsc_validate_ethtool_ss_cmd(const struct ethtool_link_ksettings *cmd)
1145   -{
1146   - struct ethtool_link_ksettings diff1 = *cmd;
1147   - struct ethtool_link_ksettings diff2 = {};
1148   -
1149   - diff1.base.speed = 0;
1150   - diff1.base.duplex = 0;
1151   - /* advertising and cmd are usually set */
1152   - ethtool_link_ksettings_zero_link_mode(&diff1, advertising);
1153   - diff1.base.cmd = 0;
1154   - /* We set port to PORT_OTHER */
1155   - diff2.base.port = PORT_OTHER;
1156   -
1157   - return !memcmp(&diff1, &diff2, sizeof(diff1));
1158   -}
1159   -
1160 1143 static void netvsc_init_settings(struct net_device *dev)
1161 1144 {
1162 1145 struct net_device_context *ndc = netdev_priv(dev);
1163 1146  
... ... @@ -1173,7 +1156,13 @@
1173 1156 struct ethtool_link_ksettings *cmd)
1174 1157 {
1175 1158 struct net_device_context *ndc = netdev_priv(dev);
  1159 + struct net_device *vf_netdev;
1176 1160  
  1161 + vf_netdev = rtnl_dereference(ndc->vf_netdev);
  1162 +
  1163 + if (vf_netdev)
  1164 + return __ethtool_get_link_ksettings(vf_netdev, cmd);
  1165 +
1177 1166 cmd->base.speed = ndc->speed;
1178 1167 cmd->base.duplex = ndc->duplex;
1179 1168 cmd->base.port = PORT_OTHER;
1180 1169  
1181 1170  
1182 1171  
... ... @@ -1185,18 +1174,18 @@
1185 1174 const struct ethtool_link_ksettings *cmd)
1186 1175 {
1187 1176 struct net_device_context *ndc = netdev_priv(dev);
1188   - u32 speed;
  1177 + struct net_device *vf_netdev = rtnl_dereference(ndc->vf_netdev);
1189 1178  
1190   - speed = cmd->base.speed;
1191   - if (!ethtool_validate_speed(speed) ||
1192   - !ethtool_validate_duplex(cmd->base.duplex) ||
1193   - !netvsc_validate_ethtool_ss_cmd(cmd))
1194   - return -EINVAL;
  1179 + if (vf_netdev) {
  1180 + if (!vf_netdev->ethtool_ops->set_link_ksettings)
  1181 + return -EOPNOTSUPP;
1195 1182  
1196   - ndc->speed = speed;
1197   - ndc->duplex = cmd->base.duplex;
  1183 + return vf_netdev->ethtool_ops->set_link_ksettings(vf_netdev,
  1184 + cmd);
  1185 + }
1198 1186  
1199   - return 0;
  1187 + return ethtool_virtdev_set_link_ksettings(dev, cmd,
  1188 + &ndc->speed, &ndc->duplex);
1200 1189 }
1201 1190  
1202 1191 static int netvsc_change_mtu(struct net_device *ndev, int mtu)
drivers/net/virtio_net.c
... ... @@ -2178,48 +2178,13 @@
2178 2178 channels->other_count = 0;
2179 2179 }
2180 2180  
2181   -/* Check if the user is trying to change anything besides speed/duplex */
2182   -static bool
2183   -virtnet_validate_ethtool_cmd(const struct ethtool_link_ksettings *cmd)
2184   -{
2185   - struct ethtool_link_ksettings diff1 = *cmd;
2186   - struct ethtool_link_ksettings diff2 = {};
2187   -
2188   - /* cmd is always set so we need to clear it, validate the port type
2189   - * and also without autonegotiation we can ignore advertising
2190   - */
2191   - diff1.base.speed = 0;
2192   - diff2.base.port = PORT_OTHER;
2193   - ethtool_link_ksettings_zero_link_mode(&diff1, advertising);
2194   - diff1.base.duplex = 0;
2195   - diff1.base.cmd = 0;
2196   - diff1.base.link_mode_masks_nwords = 0;
2197   -
2198   - return !memcmp(&diff1.base, &diff2.base, sizeof(diff1.base)) &&
2199   - bitmap_empty(diff1.link_modes.supported,
2200   - __ETHTOOL_LINK_MODE_MASK_NBITS) &&
2201   - bitmap_empty(diff1.link_modes.advertising,
2202   - __ETHTOOL_LINK_MODE_MASK_NBITS) &&
2203   - bitmap_empty(diff1.link_modes.lp_advertising,
2204   - __ETHTOOL_LINK_MODE_MASK_NBITS);
2205   -}
2206   -
2207 2181 static int virtnet_set_link_ksettings(struct net_device *dev,
2208 2182 const struct ethtool_link_ksettings *cmd)
2209 2183 {
2210 2184 struct virtnet_info *vi = netdev_priv(dev);
2211   - u32 speed;
2212 2185  
2213   - speed = cmd->base.speed;
2214   - /* don't allow custom speed and duplex */
2215   - if (!ethtool_validate_speed(speed) ||
2216   - !ethtool_validate_duplex(cmd->base.duplex) ||
2217   - !virtnet_validate_ethtool_cmd(cmd))
2218   - return -EINVAL;
2219   - vi->speed = speed;
2220   - vi->duplex = cmd->base.duplex;
2221   -
2222   - return 0;
  2186 + return ethtool_virtdev_set_link_ksettings(dev, cmd,
  2187 + &vi->speed, &vi->duplex);
2223 2188 }
2224 2189  
2225 2190 static int virtnet_get_link_ksettings(struct net_device *dev,