diff options
author | Haiyang Zhang <haiyangz@microsoft.com> | 2018-09-21 14:20:36 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-09-22 20:23:16 -0400 |
commit | d6792a5a07479d27147c01ff22041409d5e4ce4c (patch) | |
tree | 9fa467aff34010e914bc3b5628407929727ed889 | |
parent | c8e4eff4675f22ad1110141ed9e62102d4d77e1c (diff) |
hv_netvsc: Add handler for LRO setting change
This patch adds the handler for LRO setting change, so that a user
can use ethtool command to enable / disable LRO feature.
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/hyperv/hyperv_net.h | 4 | ||||
-rw-r--r-- | drivers/net/hyperv/netvsc_drv.c | 30 | ||||
-rw-r--r-- | drivers/net/hyperv/rndis_filter.c | 11 |
3 files changed, 42 insertions, 3 deletions
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h index 7f1603dc8128..ef6f766f6389 100644 --- a/drivers/net/hyperv/hyperv_net.h +++ b/drivers/net/hyperv/hyperv_net.h | |||
@@ -185,6 +185,7 @@ struct rndis_device { | |||
185 | 185 | ||
186 | /* Interface */ | 186 | /* Interface */ |
187 | struct rndis_message; | 187 | struct rndis_message; |
188 | struct ndis_offload_params; | ||
188 | struct netvsc_device; | 189 | struct netvsc_device; |
189 | struct netvsc_channel; | 190 | struct netvsc_channel; |
190 | struct net_device_context; | 191 | struct net_device_context; |
@@ -218,6 +219,9 @@ void rndis_filter_device_remove(struct hv_device *dev, | |||
218 | struct netvsc_device *nvdev); | 219 | struct netvsc_device *nvdev); |
219 | int rndis_filter_set_rss_param(struct rndis_device *rdev, | 220 | int rndis_filter_set_rss_param(struct rndis_device *rdev, |
220 | const u8 *key); | 221 | const u8 *key); |
222 | int rndis_filter_set_offload_params(struct net_device *ndev, | ||
223 | struct netvsc_device *nvdev, | ||
224 | struct ndis_offload_params *req_offloads); | ||
221 | int rndis_filter_receive(struct net_device *ndev, | 225 | int rndis_filter_receive(struct net_device *ndev, |
222 | struct netvsc_device *net_dev, | 226 | struct netvsc_device *net_dev, |
223 | struct netvsc_channel *nvchan, | 227 | struct netvsc_channel *nvchan, |
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index f8c18370d9d1..ec699741170b 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c | |||
@@ -1006,6 +1006,8 @@ static void netvsc_init_settings(struct net_device *dev) | |||
1006 | 1006 | ||
1007 | ndc->speed = SPEED_UNKNOWN; | 1007 | ndc->speed = SPEED_UNKNOWN; |
1008 | ndc->duplex = DUPLEX_FULL; | 1008 | ndc->duplex = DUPLEX_FULL; |
1009 | |||
1010 | dev->features = NETIF_F_LRO; | ||
1009 | } | 1011 | } |
1010 | 1012 | ||
1011 | static int netvsc_get_link_ksettings(struct net_device *dev, | 1013 | static int netvsc_get_link_ksettings(struct net_device *dev, |
@@ -1733,6 +1735,33 @@ static int netvsc_set_ringparam(struct net_device *ndev, | |||
1733 | return ret; | 1735 | return ret; |
1734 | } | 1736 | } |
1735 | 1737 | ||
1738 | static int netvsc_set_features(struct net_device *ndev, | ||
1739 | netdev_features_t features) | ||
1740 | { | ||
1741 | netdev_features_t change = features ^ ndev->features; | ||
1742 | struct net_device_context *ndevctx = netdev_priv(ndev); | ||
1743 | struct netvsc_device *nvdev = rtnl_dereference(ndevctx->nvdev); | ||
1744 | struct ndis_offload_params offloads; | ||
1745 | |||
1746 | if (!nvdev || nvdev->destroy) | ||
1747 | return -ENODEV; | ||
1748 | |||
1749 | if (!(change & NETIF_F_LRO)) | ||
1750 | return 0; | ||
1751 | |||
1752 | memset(&offloads, 0, sizeof(struct ndis_offload_params)); | ||
1753 | |||
1754 | if (features & NETIF_F_LRO) { | ||
1755 | offloads.rsc_ip_v4 = NDIS_OFFLOAD_PARAMETERS_RSC_ENABLED; | ||
1756 | offloads.rsc_ip_v6 = NDIS_OFFLOAD_PARAMETERS_RSC_ENABLED; | ||
1757 | } else { | ||
1758 | offloads.rsc_ip_v4 = NDIS_OFFLOAD_PARAMETERS_RSC_DISABLED; | ||
1759 | offloads.rsc_ip_v6 = NDIS_OFFLOAD_PARAMETERS_RSC_DISABLED; | ||
1760 | } | ||
1761 | |||
1762 | return rndis_filter_set_offload_params(ndev, nvdev, &offloads); | ||
1763 | } | ||
1764 | |||
1736 | static u32 netvsc_get_msglevel(struct net_device *ndev) | 1765 | static u32 netvsc_get_msglevel(struct net_device *ndev) |
1737 | { | 1766 | { |
1738 | struct net_device_context *ndev_ctx = netdev_priv(ndev); | 1767 | struct net_device_context *ndev_ctx = netdev_priv(ndev); |
@@ -1776,6 +1805,7 @@ static const struct net_device_ops device_ops = { | |||
1776 | .ndo_start_xmit = netvsc_start_xmit, | 1805 | .ndo_start_xmit = netvsc_start_xmit, |
1777 | .ndo_change_rx_flags = netvsc_change_rx_flags, | 1806 | .ndo_change_rx_flags = netvsc_change_rx_flags, |
1778 | .ndo_set_rx_mode = netvsc_set_rx_mode, | 1807 | .ndo_set_rx_mode = netvsc_set_rx_mode, |
1808 | .ndo_set_features = netvsc_set_features, | ||
1779 | .ndo_change_mtu = netvsc_change_mtu, | 1809 | .ndo_change_mtu = netvsc_change_mtu, |
1780 | .ndo_validate_addr = eth_validate_addr, | 1810 | .ndo_validate_addr = eth_validate_addr, |
1781 | .ndo_set_mac_address = netvsc_set_mac_addr, | 1811 | .ndo_set_mac_address = netvsc_set_mac_addr, |
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c index f3ac66386297..8b537a049c1e 100644 --- a/drivers/net/hyperv/rndis_filter.c +++ b/drivers/net/hyperv/rndis_filter.c | |||
@@ -716,7 +716,7 @@ cleanup: | |||
716 | return ret; | 716 | return ret; |
717 | } | 717 | } |
718 | 718 | ||
719 | static int | 719 | int |
720 | rndis_filter_set_offload_params(struct net_device *ndev, | 720 | rndis_filter_set_offload_params(struct net_device *ndev, |
721 | struct netvsc_device *nvdev, | 721 | struct netvsc_device *nvdev, |
722 | struct ndis_offload_params *req_offloads) | 722 | struct ndis_offload_params *req_offloads) |
@@ -1246,8 +1246,13 @@ static int rndis_netdev_set_hwcaps(struct rndis_device *rndis_device, | |||
1246 | if (hwcaps.rsc.ip4 && hwcaps.rsc.ip6) { | 1246 | if (hwcaps.rsc.ip4 && hwcaps.rsc.ip6) { |
1247 | net->hw_features |= NETIF_F_LRO; | 1247 | net->hw_features |= NETIF_F_LRO; |
1248 | 1248 | ||
1249 | offloads.rsc_ip_v4 = NDIS_OFFLOAD_PARAMETERS_RSC_ENABLED; | 1249 | if (net->features & NETIF_F_LRO) { |
1250 | offloads.rsc_ip_v6 = NDIS_OFFLOAD_PARAMETERS_RSC_ENABLED; | 1250 | offloads.rsc_ip_v4 = NDIS_OFFLOAD_PARAMETERS_RSC_ENABLED; |
1251 | offloads.rsc_ip_v6 = NDIS_OFFLOAD_PARAMETERS_RSC_ENABLED; | ||
1252 | } else { | ||
1253 | offloads.rsc_ip_v4 = NDIS_OFFLOAD_PARAMETERS_RSC_DISABLED; | ||
1254 | offloads.rsc_ip_v6 = NDIS_OFFLOAD_PARAMETERS_RSC_DISABLED; | ||
1255 | } | ||
1251 | } | 1256 | } |
1252 | 1257 | ||
1253 | /* In case some hw_features disappeared we need to remove them from | 1258 | /* In case some hw_features disappeared we need to remove them from |