diff options
Diffstat (limited to 'drivers/net/hyperv/netvsc_drv.c')
| -rw-r--r-- | drivers/net/hyperv/netvsc_drv.c | 145 |
1 files changed, 92 insertions, 53 deletions
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 91ed15ea5883..256adbd044f5 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c | |||
| @@ -370,7 +370,7 @@ static u32 fill_pg_buf(struct page *page, u32 offset, u32 len, | |||
| 370 | { | 370 | { |
| 371 | int j = 0; | 371 | int j = 0; |
| 372 | 372 | ||
| 373 | /* Deal with compund pages by ignoring unused part | 373 | /* Deal with compound pages by ignoring unused part |
| 374 | * of the page. | 374 | * of the page. |
| 375 | */ | 375 | */ |
| 376 | page += (offset >> PAGE_SHIFT); | 376 | page += (offset >> PAGE_SHIFT); |
| @@ -858,6 +858,39 @@ static void netvsc_get_channels(struct net_device *net, | |||
| 858 | } | 858 | } |
| 859 | } | 859 | } |
| 860 | 860 | ||
| 861 | /* Alloc struct netvsc_device_info, and initialize it from either existing | ||
| 862 | * struct netvsc_device, or from default values. | ||
| 863 | */ | ||
| 864 | static struct netvsc_device_info *netvsc_devinfo_get | ||
| 865 | (struct netvsc_device *nvdev) | ||
| 866 | { | ||
| 867 | struct netvsc_device_info *dev_info; | ||
| 868 | |||
| 869 | dev_info = kzalloc(sizeof(*dev_info), GFP_ATOMIC); | ||
| 870 | |||
| 871 | if (!dev_info) | ||
| 872 | return NULL; | ||
| 873 | |||
| 874 | if (nvdev) { | ||
| 875 | dev_info->num_chn = nvdev->num_chn; | ||
| 876 | dev_info->send_sections = nvdev->send_section_cnt; | ||
| 877 | dev_info->send_section_size = nvdev->send_section_size; | ||
| 878 | dev_info->recv_sections = nvdev->recv_section_cnt; | ||
| 879 | dev_info->recv_section_size = nvdev->recv_section_size; | ||
| 880 | |||
| 881 | memcpy(dev_info->rss_key, nvdev->extension->rss_key, | ||
| 882 | NETVSC_HASH_KEYLEN); | ||
| 883 | } else { | ||
| 884 | dev_info->num_chn = VRSS_CHANNEL_DEFAULT; | ||
| 885 | dev_info->send_sections = NETVSC_DEFAULT_TX; | ||
| 886 | dev_info->send_section_size = NETVSC_SEND_SECTION_SIZE; | ||
| 887 | dev_info->recv_sections = NETVSC_DEFAULT_RX; | ||
| 888 | dev_info->recv_section_size = NETVSC_RECV_SECTION_SIZE; | ||
| 889 | } | ||
| 890 | |||
| 891 | return dev_info; | ||
| 892 | } | ||
| 893 | |||
| 861 | static int netvsc_detach(struct net_device *ndev, | 894 | static int netvsc_detach(struct net_device *ndev, |
| 862 | struct netvsc_device *nvdev) | 895 | struct netvsc_device *nvdev) |
| 863 | { | 896 | { |
| @@ -909,7 +942,7 @@ static int netvsc_attach(struct net_device *ndev, | |||
| 909 | return PTR_ERR(nvdev); | 942 | return PTR_ERR(nvdev); |
| 910 | 943 | ||
| 911 | if (nvdev->num_chn > 1) { | 944 | if (nvdev->num_chn > 1) { |
| 912 | ret = rndis_set_subchannel(ndev, nvdev); | 945 | ret = rndis_set_subchannel(ndev, nvdev, dev_info); |
| 913 | 946 | ||
| 914 | /* if unavailable, just proceed with one queue */ | 947 | /* if unavailable, just proceed with one queue */ |
| 915 | if (ret) { | 948 | if (ret) { |
| @@ -943,7 +976,7 @@ static int netvsc_set_channels(struct net_device *net, | |||
| 943 | struct net_device_context *net_device_ctx = netdev_priv(net); | 976 | struct net_device_context *net_device_ctx = netdev_priv(net); |
| 944 | struct netvsc_device *nvdev = rtnl_dereference(net_device_ctx->nvdev); | 977 | struct netvsc_device *nvdev = rtnl_dereference(net_device_ctx->nvdev); |
| 945 | unsigned int orig, count = channels->combined_count; | 978 | unsigned int orig, count = channels->combined_count; |
| 946 | struct netvsc_device_info device_info; | 979 | struct netvsc_device_info *device_info; |
| 947 | int ret; | 980 | int ret; |
| 948 | 981 | ||
| 949 | /* We do not support separate count for rx, tx, or other */ | 982 | /* We do not support separate count for rx, tx, or other */ |
| @@ -962,24 +995,26 @@ static int netvsc_set_channels(struct net_device *net, | |||
| 962 | 995 | ||
| 963 | orig = nvdev->num_chn; | 996 | orig = nvdev->num_chn; |
| 964 | 997 | ||
| 965 | memset(&device_info, 0, sizeof(device_info)); | 998 | device_info = netvsc_devinfo_get(nvdev); |
| 966 | device_info.num_chn = count; | 999 | |
| 967 | device_info.send_sections = nvdev->send_section_cnt; | 1000 | if (!device_info) |
| 968 | device_info.send_section_size = nvdev->send_section_size; | 1001 | return -ENOMEM; |
| 969 | device_info.recv_sections = nvdev->recv_section_cnt; | 1002 | |
| 970 | device_info.recv_section_size = nvdev->recv_section_size; | 1003 | device_info->num_chn = count; |
| 971 | 1004 | ||
| 972 | ret = netvsc_detach(net, nvdev); | 1005 | ret = netvsc_detach(net, nvdev); |
| 973 | if (ret) | 1006 | if (ret) |
| 974 | return ret; | 1007 | goto out; |
| 975 | 1008 | ||
| 976 | ret = netvsc_attach(net, &device_info); | 1009 | ret = netvsc_attach(net, device_info); |
| 977 | if (ret) { | 1010 | if (ret) { |
| 978 | device_info.num_chn = orig; | 1011 | device_info->num_chn = orig; |
| 979 | if (netvsc_attach(net, &device_info)) | 1012 | if (netvsc_attach(net, device_info)) |
| 980 | netdev_err(net, "restoring channel setting failed\n"); | 1013 | netdev_err(net, "restoring channel setting failed\n"); |
| 981 | } | 1014 | } |
| 982 | 1015 | ||
| 1016 | out: | ||
| 1017 | kfree(device_info); | ||
| 983 | return ret; | 1018 | return ret; |
| 984 | } | 1019 | } |
| 985 | 1020 | ||
| @@ -1048,48 +1083,45 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu) | |||
| 1048 | struct net_device *vf_netdev = rtnl_dereference(ndevctx->vf_netdev); | 1083 | struct net_device *vf_netdev = rtnl_dereference(ndevctx->vf_netdev); |
| 1049 | struct netvsc_device *nvdev = rtnl_dereference(ndevctx->nvdev); | 1084 | struct netvsc_device *nvdev = rtnl_dereference(ndevctx->nvdev); |
| 1050 | int orig_mtu = ndev->mtu; | 1085 | int orig_mtu = ndev->mtu; |
| 1051 | struct netvsc_device_info device_info; | 1086 | struct netvsc_device_info *device_info; |
| 1052 | int ret = 0; | 1087 | int ret = 0; |
| 1053 | 1088 | ||
| 1054 | if (!nvdev || nvdev->destroy) | 1089 | if (!nvdev || nvdev->destroy) |
| 1055 | return -ENODEV; | 1090 | return -ENODEV; |
| 1056 | 1091 | ||
| 1092 | device_info = netvsc_devinfo_get(nvdev); | ||
| 1093 | |||
| 1094 | if (!device_info) | ||
| 1095 | return -ENOMEM; | ||
| 1096 | |||
| 1057 | /* Change MTU of underlying VF netdev first. */ | 1097 | /* Change MTU of underlying VF netdev first. */ |
| 1058 | if (vf_netdev) { | 1098 | if (vf_netdev) { |
| 1059 | ret = dev_set_mtu(vf_netdev, mtu); | 1099 | ret = dev_set_mtu(vf_netdev, mtu); |
| 1060 | if (ret) | 1100 | if (ret) |
| 1061 | return ret; | 1101 | goto out; |
| 1062 | } | 1102 | } |
| 1063 | 1103 | ||
| 1064 | memset(&device_info, 0, sizeof(device_info)); | ||
| 1065 | device_info.num_chn = nvdev->num_chn; | ||
| 1066 | device_info.send_sections = nvdev->send_section_cnt; | ||
| 1067 | device_info.send_section_size = nvdev->send_section_size; | ||
| 1068 | device_info.recv_sections = nvdev->recv_section_cnt; | ||
| 1069 | device_info.recv_section_size = nvdev->recv_section_size; | ||
| 1070 | |||
| 1071 | ret = netvsc_detach(ndev, nvdev); | 1104 | ret = netvsc_detach(ndev, nvdev); |
| 1072 | if (ret) | 1105 | if (ret) |
| 1073 | goto rollback_vf; | 1106 | goto rollback_vf; |
| 1074 | 1107 | ||
| 1075 | ndev->mtu = mtu; | 1108 | ndev->mtu = mtu; |
| 1076 | 1109 | ||
| 1077 | ret = netvsc_attach(ndev, &device_info); | 1110 | ret = netvsc_attach(ndev, device_info); |
| 1078 | if (ret) | 1111 | if (!ret) |
| 1079 | goto rollback; | 1112 | goto out; |
| 1080 | |||
| 1081 | return 0; | ||
| 1082 | 1113 | ||
| 1083 | rollback: | ||
| 1084 | /* Attempt rollback to original MTU */ | 1114 | /* Attempt rollback to original MTU */ |
| 1085 | ndev->mtu = orig_mtu; | 1115 | ndev->mtu = orig_mtu; |
| 1086 | 1116 | ||
| 1087 | if (netvsc_attach(ndev, &device_info)) | 1117 | if (netvsc_attach(ndev, device_info)) |
| 1088 | netdev_err(ndev, "restoring mtu failed\n"); | 1118 | netdev_err(ndev, "restoring mtu failed\n"); |
| 1089 | rollback_vf: | 1119 | rollback_vf: |
| 1090 | if (vf_netdev) | 1120 | if (vf_netdev) |
| 1091 | dev_set_mtu(vf_netdev, orig_mtu); | 1121 | dev_set_mtu(vf_netdev, orig_mtu); |
| 1092 | 1122 | ||
| 1123 | out: | ||
| 1124 | kfree(device_info); | ||
| 1093 | return ret; | 1125 | return ret; |
| 1094 | } | 1126 | } |
| 1095 | 1127 | ||
| @@ -1674,7 +1706,7 @@ static int netvsc_set_ringparam(struct net_device *ndev, | |||
| 1674 | { | 1706 | { |
| 1675 | struct net_device_context *ndevctx = netdev_priv(ndev); | 1707 | struct net_device_context *ndevctx = netdev_priv(ndev); |
| 1676 | struct netvsc_device *nvdev = rtnl_dereference(ndevctx->nvdev); | 1708 | struct netvsc_device *nvdev = rtnl_dereference(ndevctx->nvdev); |
| 1677 | struct netvsc_device_info device_info; | 1709 | struct netvsc_device_info *device_info; |
| 1678 | struct ethtool_ringparam orig; | 1710 | struct ethtool_ringparam orig; |
| 1679 | u32 new_tx, new_rx; | 1711 | u32 new_tx, new_rx; |
| 1680 | int ret = 0; | 1712 | int ret = 0; |
| @@ -1694,26 +1726,29 @@ static int netvsc_set_ringparam(struct net_device *ndev, | |||
| 1694 | new_rx == orig.rx_pending) | 1726 | new_rx == orig.rx_pending) |
| 1695 | return 0; /* no change */ | 1727 | return 0; /* no change */ |
| 1696 | 1728 | ||
| 1697 | memset(&device_info, 0, sizeof(device_info)); | 1729 | device_info = netvsc_devinfo_get(nvdev); |
| 1698 | device_info.num_chn = nvdev->num_chn; | 1730 | |
| 1699 | device_info.send_sections = new_tx; | 1731 | if (!device_info) |
| 1700 | device_info.send_section_size = nvdev->send_section_size; | 1732 | return -ENOMEM; |
| 1701 | device_info.recv_sections = new_rx; | 1733 | |
| 1702 | device_info.recv_section_size = nvdev->recv_section_size; | 1734 | device_info->send_sections = new_tx; |
| 1735 | device_info->recv_sections = new_rx; | ||
| 1703 | 1736 | ||
| 1704 | ret = netvsc_detach(ndev, nvdev); | 1737 | ret = netvsc_detach(ndev, nvdev); |
| 1705 | if (ret) | 1738 | if (ret) |
| 1706 | return ret; | 1739 | goto out; |
| 1707 | 1740 | ||
| 1708 | ret = netvsc_attach(ndev, &device_info); | 1741 | ret = netvsc_attach(ndev, device_info); |
| 1709 | if (ret) { | 1742 | if (ret) { |
| 1710 | device_info.send_sections = orig.tx_pending; | 1743 | device_info->send_sections = orig.tx_pending; |
| 1711 | device_info.recv_sections = orig.rx_pending; | 1744 | device_info->recv_sections = orig.rx_pending; |
| 1712 | 1745 | ||
| 1713 | if (netvsc_attach(ndev, &device_info)) | 1746 | if (netvsc_attach(ndev, device_info)) |
| 1714 | netdev_err(ndev, "restoring ringparam failed"); | 1747 | netdev_err(ndev, "restoring ringparam failed"); |
| 1715 | } | 1748 | } |
| 1716 | 1749 | ||
| 1750 | out: | ||
| 1751 | kfree(device_info); | ||
| 1717 | return ret; | 1752 | return ret; |
| 1718 | } | 1753 | } |
| 1719 | 1754 | ||
| @@ -2088,7 +2123,7 @@ static int netvsc_register_vf(struct net_device *vf_netdev) | |||
| 2088 | if (!netvsc_dev || rtnl_dereference(net_device_ctx->vf_netdev)) | 2123 | if (!netvsc_dev || rtnl_dereference(net_device_ctx->vf_netdev)) |
| 2089 | return NOTIFY_DONE; | 2124 | return NOTIFY_DONE; |
| 2090 | 2125 | ||
| 2091 | /* if syntihetic interface is a different namespace, | 2126 | /* if synthetic interface is a different namespace, |
| 2092 | * then move the VF to that namespace; join will be | 2127 | * then move the VF to that namespace; join will be |
| 2093 | * done again in that context. | 2128 | * done again in that context. |
| 2094 | */ | 2129 | */ |
| @@ -2167,7 +2202,7 @@ static int netvsc_probe(struct hv_device *dev, | |||
| 2167 | { | 2202 | { |
| 2168 | struct net_device *net = NULL; | 2203 | struct net_device *net = NULL; |
| 2169 | struct net_device_context *net_device_ctx; | 2204 | struct net_device_context *net_device_ctx; |
| 2170 | struct netvsc_device_info device_info; | 2205 | struct netvsc_device_info *device_info = NULL; |
| 2171 | struct netvsc_device *nvdev; | 2206 | struct netvsc_device *nvdev; |
| 2172 | int ret = -ENOMEM; | 2207 | int ret = -ENOMEM; |
| 2173 | 2208 | ||
| @@ -2214,21 +2249,21 @@ static int netvsc_probe(struct hv_device *dev, | |||
| 2214 | netif_set_real_num_rx_queues(net, 1); | 2249 | netif_set_real_num_rx_queues(net, 1); |
| 2215 | 2250 | ||
| 2216 | /* Notify the netvsc driver of the new device */ | 2251 | /* Notify the netvsc driver of the new device */ |
| 2217 | memset(&device_info, 0, sizeof(device_info)); | 2252 | device_info = netvsc_devinfo_get(NULL); |
| 2218 | device_info.num_chn = VRSS_CHANNEL_DEFAULT; | 2253 | |
| 2219 | device_info.send_sections = NETVSC_DEFAULT_TX; | 2254 | if (!device_info) { |
| 2220 | device_info.send_section_size = NETVSC_SEND_SECTION_SIZE; | 2255 | ret = -ENOMEM; |
| 2221 | device_info.recv_sections = NETVSC_DEFAULT_RX; | 2256 | goto devinfo_failed; |
| 2222 | device_info.recv_section_size = NETVSC_RECV_SECTION_SIZE; | 2257 | } |
| 2223 | 2258 | ||
| 2224 | nvdev = rndis_filter_device_add(dev, &device_info); | 2259 | nvdev = rndis_filter_device_add(dev, device_info); |
| 2225 | if (IS_ERR(nvdev)) { | 2260 | if (IS_ERR(nvdev)) { |
| 2226 | ret = PTR_ERR(nvdev); | 2261 | ret = PTR_ERR(nvdev); |
| 2227 | netdev_err(net, "unable to add netvsc device (ret %d)\n", ret); | 2262 | netdev_err(net, "unable to add netvsc device (ret %d)\n", ret); |
| 2228 | goto rndis_failed; | 2263 | goto rndis_failed; |
| 2229 | } | 2264 | } |
| 2230 | 2265 | ||
| 2231 | memcpy(net->dev_addr, device_info.mac_adr, ETH_ALEN); | 2266 | memcpy(net->dev_addr, device_info->mac_adr, ETH_ALEN); |
| 2232 | 2267 | ||
| 2233 | /* We must get rtnl lock before scheduling nvdev->subchan_work, | 2268 | /* We must get rtnl lock before scheduling nvdev->subchan_work, |
| 2234 | * otherwise netvsc_subchan_work() can get rtnl lock first and wait | 2269 | * otherwise netvsc_subchan_work() can get rtnl lock first and wait |
| @@ -2236,7 +2271,7 @@ static int netvsc_probe(struct hv_device *dev, | |||
| 2236 | * netvsc_probe() can't get rtnl lock and as a result vmbus_onoffer() | 2271 | * netvsc_probe() can't get rtnl lock and as a result vmbus_onoffer() |
| 2237 | * -> ... -> device_add() -> ... -> __device_attach() can't get | 2272 | * -> ... -> device_add() -> ... -> __device_attach() can't get |
| 2238 | * the device lock, so all the subchannels can't be processed -- | 2273 | * the device lock, so all the subchannels can't be processed -- |
| 2239 | * finally netvsc_subchan_work() hangs for ever. | 2274 | * finally netvsc_subchan_work() hangs forever. |
| 2240 | */ | 2275 | */ |
| 2241 | rtnl_lock(); | 2276 | rtnl_lock(); |
| 2242 | 2277 | ||
| @@ -2266,12 +2301,16 @@ static int netvsc_probe(struct hv_device *dev, | |||
| 2266 | 2301 | ||
| 2267 | list_add(&net_device_ctx->list, &netvsc_dev_list); | 2302 | list_add(&net_device_ctx->list, &netvsc_dev_list); |
| 2268 | rtnl_unlock(); | 2303 | rtnl_unlock(); |
| 2304 | |||
| 2305 | kfree(device_info); | ||
| 2269 | return 0; | 2306 | return 0; |
| 2270 | 2307 | ||
| 2271 | register_failed: | 2308 | register_failed: |
| 2272 | rtnl_unlock(); | 2309 | rtnl_unlock(); |
| 2273 | rndis_filter_device_remove(dev, nvdev); | 2310 | rndis_filter_device_remove(dev, nvdev); |
| 2274 | rndis_failed: | 2311 | rndis_failed: |
| 2312 | kfree(device_info); | ||
| 2313 | devinfo_failed: | ||
| 2275 | free_percpu(net_device_ctx->vf_stats); | 2314 | free_percpu(net_device_ctx->vf_stats); |
| 2276 | no_stats: | 2315 | no_stats: |
| 2277 | hv_set_drvdata(dev, NULL); | 2316 | hv_set_drvdata(dev, NULL); |
