Commit 9aedc6e2f1c6708120b80748556fb6ad0567d15d
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
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, |