diff options
Diffstat (limited to 'drivers/net/hyperv')
| -rw-r--r-- | drivers/net/hyperv/hyperv_net.h | 12 | ||||
| -rw-r--r-- | drivers/net/hyperv/netvsc.c | 4 | ||||
| -rw-r--r-- | drivers/net/hyperv/netvsc_drv.c | 145 | ||||
| -rw-r--r-- | drivers/net/hyperv/rndis_filter.c | 36 |
4 files changed, 129 insertions, 68 deletions
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h index ef6f766f6389..e859ae2e42d5 100644 --- a/drivers/net/hyperv/hyperv_net.h +++ b/drivers/net/hyperv/hyperv_net.h | |||
| @@ -144,6 +144,8 @@ struct hv_netvsc_packet { | |||
| 144 | u32 total_data_buflen; | 144 | u32 total_data_buflen; |
| 145 | }; | 145 | }; |
| 146 | 146 | ||
| 147 | #define NETVSC_HASH_KEYLEN 40 | ||
| 148 | |||
| 147 | struct netvsc_device_info { | 149 | struct netvsc_device_info { |
| 148 | unsigned char mac_adr[ETH_ALEN]; | 150 | unsigned char mac_adr[ETH_ALEN]; |
| 149 | u32 num_chn; | 151 | u32 num_chn; |
| @@ -151,6 +153,8 @@ struct netvsc_device_info { | |||
| 151 | u32 recv_sections; | 153 | u32 recv_sections; |
| 152 | u32 send_section_size; | 154 | u32 send_section_size; |
| 153 | u32 recv_section_size; | 155 | u32 recv_section_size; |
| 156 | |||
| 157 | u8 rss_key[NETVSC_HASH_KEYLEN]; | ||
| 154 | }; | 158 | }; |
| 155 | 159 | ||
| 156 | enum rndis_device_state { | 160 | enum rndis_device_state { |
| @@ -160,8 +164,6 @@ enum rndis_device_state { | |||
| 160 | RNDIS_DEV_DATAINITIALIZED, | 164 | RNDIS_DEV_DATAINITIALIZED, |
| 161 | }; | 165 | }; |
| 162 | 166 | ||
| 163 | #define NETVSC_HASH_KEYLEN 40 | ||
| 164 | |||
| 165 | struct rndis_device { | 167 | struct rndis_device { |
| 166 | struct net_device *ndev; | 168 | struct net_device *ndev; |
| 167 | 169 | ||
| @@ -209,7 +211,9 @@ int netvsc_recv_callback(struct net_device *net, | |||
| 209 | void netvsc_channel_cb(void *context); | 211 | void netvsc_channel_cb(void *context); |
| 210 | int netvsc_poll(struct napi_struct *napi, int budget); | 212 | int netvsc_poll(struct napi_struct *napi, int budget); |
| 211 | 213 | ||
| 212 | int rndis_set_subchannel(struct net_device *ndev, struct netvsc_device *nvdev); | 214 | int rndis_set_subchannel(struct net_device *ndev, |
| 215 | struct netvsc_device *nvdev, | ||
| 216 | struct netvsc_device_info *dev_info); | ||
| 213 | int rndis_filter_open(struct netvsc_device *nvdev); | 217 | int rndis_filter_open(struct netvsc_device *nvdev); |
| 214 | int rndis_filter_close(struct netvsc_device *nvdev); | 218 | int rndis_filter_close(struct netvsc_device *nvdev); |
| 215 | struct netvsc_device *rndis_filter_device_add(struct hv_device *dev, | 219 | struct netvsc_device *rndis_filter_device_add(struct hv_device *dev, |
| @@ -1177,7 +1181,7 @@ enum ndis_per_pkt_info_type { | |||
| 1177 | 1181 | ||
| 1178 | enum rndis_per_pkt_info_interal_type { | 1182 | enum rndis_per_pkt_info_interal_type { |
| 1179 | RNDIS_PKTINFO_ID = 1, | 1183 | RNDIS_PKTINFO_ID = 1, |
| 1180 | /* Add more memebers here */ | 1184 | /* Add more members here */ |
| 1181 | 1185 | ||
| 1182 | RNDIS_PKTINFO_MAX | 1186 | RNDIS_PKTINFO_MAX |
| 1183 | }; | 1187 | }; |
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c index 922054c1d544..813d195bbd57 100644 --- a/drivers/net/hyperv/netvsc.c +++ b/drivers/net/hyperv/netvsc.c | |||
| @@ -84,7 +84,7 @@ static void netvsc_subchan_work(struct work_struct *w) | |||
| 84 | 84 | ||
| 85 | rdev = nvdev->extension; | 85 | rdev = nvdev->extension; |
| 86 | if (rdev) { | 86 | if (rdev) { |
| 87 | ret = rndis_set_subchannel(rdev->ndev, nvdev); | 87 | ret = rndis_set_subchannel(rdev->ndev, nvdev, NULL); |
| 88 | if (ret == 0) { | 88 | if (ret == 0) { |
| 89 | netif_device_attach(rdev->ndev); | 89 | netif_device_attach(rdev->ndev); |
| 90 | } else { | 90 | } else { |
| @@ -1331,7 +1331,7 @@ void netvsc_channel_cb(void *context) | |||
| 1331 | prefetch(hv_get_ring_buffer(rbi) + rbi->priv_read_index); | 1331 | prefetch(hv_get_ring_buffer(rbi) + rbi->priv_read_index); |
| 1332 | 1332 | ||
| 1333 | if (napi_schedule_prep(&nvchan->napi)) { | 1333 | if (napi_schedule_prep(&nvchan->napi)) { |
| 1334 | /* disable interupts from host */ | 1334 | /* disable interrupts from host */ |
| 1335 | hv_begin_read(rbi); | 1335 | hv_begin_read(rbi); |
| 1336 | 1336 | ||
| 1337 | __napi_schedule_irqoff(&nvchan->napi); | 1337 | __napi_schedule_irqoff(&nvchan->napi); |
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); |
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c index 8b537a049c1e..73b60592de06 100644 --- a/drivers/net/hyperv/rndis_filter.c +++ b/drivers/net/hyperv/rndis_filter.c | |||
| @@ -774,8 +774,8 @@ cleanup: | |||
| 774 | return ret; | 774 | return ret; |
| 775 | } | 775 | } |
| 776 | 776 | ||
| 777 | int rndis_filter_set_rss_param(struct rndis_device *rdev, | 777 | static int rndis_set_rss_param_msg(struct rndis_device *rdev, |
| 778 | const u8 *rss_key) | 778 | const u8 *rss_key, u16 flag) |
| 779 | { | 779 | { |
| 780 | struct net_device *ndev = rdev->ndev; | 780 | struct net_device *ndev = rdev->ndev; |
| 781 | struct rndis_request *request; | 781 | struct rndis_request *request; |
| @@ -804,7 +804,7 @@ int rndis_filter_set_rss_param(struct rndis_device *rdev, | |||
| 804 | rssp->hdr.type = NDIS_OBJECT_TYPE_RSS_PARAMETERS; | 804 | rssp->hdr.type = NDIS_OBJECT_TYPE_RSS_PARAMETERS; |
| 805 | rssp->hdr.rev = NDIS_RECEIVE_SCALE_PARAMETERS_REVISION_2; | 805 | rssp->hdr.rev = NDIS_RECEIVE_SCALE_PARAMETERS_REVISION_2; |
| 806 | rssp->hdr.size = sizeof(struct ndis_recv_scale_param); | 806 | rssp->hdr.size = sizeof(struct ndis_recv_scale_param); |
| 807 | rssp->flag = 0; | 807 | rssp->flag = flag; |
| 808 | rssp->hashinfo = NDIS_HASH_FUNC_TOEPLITZ | NDIS_HASH_IPV4 | | 808 | rssp->hashinfo = NDIS_HASH_FUNC_TOEPLITZ | NDIS_HASH_IPV4 | |
| 809 | NDIS_HASH_TCP_IPV4 | NDIS_HASH_IPV6 | | 809 | NDIS_HASH_TCP_IPV4 | NDIS_HASH_IPV6 | |
| 810 | NDIS_HASH_TCP_IPV6; | 810 | NDIS_HASH_TCP_IPV6; |
| @@ -829,9 +829,12 @@ int rndis_filter_set_rss_param(struct rndis_device *rdev, | |||
| 829 | 829 | ||
| 830 | wait_for_completion(&request->wait_event); | 830 | wait_for_completion(&request->wait_event); |
| 831 | set_complete = &request->response_msg.msg.set_complete; | 831 | set_complete = &request->response_msg.msg.set_complete; |
| 832 | if (set_complete->status == RNDIS_STATUS_SUCCESS) | 832 | if (set_complete->status == RNDIS_STATUS_SUCCESS) { |
| 833 | memcpy(rdev->rss_key, rss_key, NETVSC_HASH_KEYLEN); | 833 | if (!(flag & NDIS_RSS_PARAM_FLAG_DISABLE_RSS) && |
| 834 | else { | 834 | !(flag & NDIS_RSS_PARAM_FLAG_HASH_KEY_UNCHANGED)) |
| 835 | memcpy(rdev->rss_key, rss_key, NETVSC_HASH_KEYLEN); | ||
| 836 | |||
| 837 | } else { | ||
| 835 | netdev_err(ndev, "Fail to set RSS parameters:0x%x\n", | 838 | netdev_err(ndev, "Fail to set RSS parameters:0x%x\n", |
| 836 | set_complete->status); | 839 | set_complete->status); |
| 837 | ret = -EINVAL; | 840 | ret = -EINVAL; |
| @@ -842,6 +845,16 @@ cleanup: | |||
| 842 | return ret; | 845 | return ret; |
| 843 | } | 846 | } |
| 844 | 847 | ||
| 848 | int rndis_filter_set_rss_param(struct rndis_device *rdev, | ||
| 849 | const u8 *rss_key) | ||
| 850 | { | ||
| 851 | /* Disable RSS before change */ | ||
| 852 | rndis_set_rss_param_msg(rdev, rss_key, | ||
| 853 | NDIS_RSS_PARAM_FLAG_DISABLE_RSS); | ||
| 854 | |||
| 855 | return rndis_set_rss_param_msg(rdev, rss_key, 0); | ||
| 856 | } | ||
| 857 | |||
| 845 | static int rndis_filter_query_device_link_status(struct rndis_device *dev, | 858 | static int rndis_filter_query_device_link_status(struct rndis_device *dev, |
| 846 | struct netvsc_device *net_device) | 859 | struct netvsc_device *net_device) |
| 847 | { | 860 | { |
| @@ -1121,7 +1134,9 @@ static void netvsc_sc_open(struct vmbus_channel *new_sc) | |||
| 1121 | * This breaks overlap of processing the host message for the | 1134 | * This breaks overlap of processing the host message for the |
| 1122 | * new primary channel with the initialization of sub-channels. | 1135 | * new primary channel with the initialization of sub-channels. |
| 1123 | */ | 1136 | */ |
| 1124 | int rndis_set_subchannel(struct net_device *ndev, struct netvsc_device *nvdev) | 1137 | int rndis_set_subchannel(struct net_device *ndev, |
| 1138 | struct netvsc_device *nvdev, | ||
| 1139 | struct netvsc_device_info *dev_info) | ||
| 1125 | { | 1140 | { |
| 1126 | struct nvsp_message *init_packet = &nvdev->channel_init_pkt; | 1141 | struct nvsp_message *init_packet = &nvdev->channel_init_pkt; |
| 1127 | struct net_device_context *ndev_ctx = netdev_priv(ndev); | 1142 | struct net_device_context *ndev_ctx = netdev_priv(ndev); |
| @@ -1161,8 +1176,11 @@ int rndis_set_subchannel(struct net_device *ndev, struct netvsc_device *nvdev) | |||
| 1161 | wait_event(nvdev->subchan_open, | 1176 | wait_event(nvdev->subchan_open, |
| 1162 | atomic_read(&nvdev->open_chn) == nvdev->num_chn); | 1177 | atomic_read(&nvdev->open_chn) == nvdev->num_chn); |
| 1163 | 1178 | ||
| 1164 | /* ignore failues from setting rss parameters, still have channels */ | 1179 | /* ignore failures from setting rss parameters, still have channels */ |
| 1165 | rndis_filter_set_rss_param(rdev, netvsc_hash_key); | 1180 | if (dev_info) |
| 1181 | rndis_filter_set_rss_param(rdev, dev_info->rss_key); | ||
| 1182 | else | ||
| 1183 | rndis_filter_set_rss_param(rdev, netvsc_hash_key); | ||
| 1166 | 1184 | ||
| 1167 | netif_set_real_num_tx_queues(ndev, nvdev->num_chn); | 1185 | netif_set_real_num_tx_queues(ndev, nvdev->num_chn); |
| 1168 | netif_set_real_num_rx_queues(ndev, nvdev->num_chn); | 1186 | netif_set_real_num_rx_queues(ndev, nvdev->num_chn); |
