diff options
author | Haiyang Zhang <haiyangz@microsoft.com> | 2014-05-21 15:55:39 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-05-23 14:49:00 -0400 |
commit | 307f099520b66504cf6c5638f3f404c48b9fb45b (patch) | |
tree | 1e401d359547bb836ad7cce9214bf7fd578c5b91 /drivers/net/hyperv | |
parent | 915f15ca52d8aefa253e0f13c7daa33b9f6ab399 (diff) |
hyperv: Add hash value into RNDIS Per-packet info
It passes the hash value as the RNDIS Per-packet info to the Hyper-V host,
so that the send completion notices can be spread across multiple channels.
MS-TFS: 140273
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/hyperv')
-rw-r--r-- | drivers/net/hyperv/hyperv_net.h | 4 | ||||
-rw-r--r-- | drivers/net/hyperv/netvsc_drv.c | 18 |
2 files changed, 18 insertions, 4 deletions
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h index 4b7df5a5c966..6cc37c15e0bf 100644 --- a/drivers/net/hyperv/hyperv_net.h +++ b/drivers/net/hyperv/hyperv_net.h | |||
@@ -791,6 +791,7 @@ enum ndis_per_pkt_info_type { | |||
791 | IEEE_8021Q_INFO, | 791 | IEEE_8021Q_INFO, |
792 | ORIGINAL_PKTINFO, | 792 | ORIGINAL_PKTINFO, |
793 | PACKET_CANCEL_ID, | 793 | PACKET_CANCEL_ID, |
794 | NBL_HASH_VALUE = PACKET_CANCEL_ID, | ||
794 | ORIGINAL_NET_BUFLIST, | 795 | ORIGINAL_NET_BUFLIST, |
795 | CACHED_NET_BUFLIST, | 796 | CACHED_NET_BUFLIST, |
796 | SHORT_PKT_PADINFO, | 797 | SHORT_PKT_PADINFO, |
@@ -937,6 +938,9 @@ struct ndis_tcp_lso_info { | |||
937 | #define NDIS_LSO_PPI_SIZE (sizeof(struct rndis_per_packet_info) + \ | 938 | #define NDIS_LSO_PPI_SIZE (sizeof(struct rndis_per_packet_info) + \ |
938 | sizeof(struct ndis_tcp_lso_info)) | 939 | sizeof(struct ndis_tcp_lso_info)) |
939 | 940 | ||
941 | #define NDIS_HASH_PPI_SIZE (sizeof(struct rndis_per_packet_info) + \ | ||
942 | sizeof(u32)) | ||
943 | |||
940 | /* Format of Information buffer passed in a SetRequest for the OID */ | 944 | /* Format of Information buffer passed in a SetRequest for the OID */ |
941 | /* OID_GEN_RNDIS_CONFIG_PARAMETER. */ | 945 | /* OID_GEN_RNDIS_CONFIG_PARAMETER. */ |
942 | struct rndis_config_parameter_info { | 946 | struct rndis_config_parameter_info { |
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 2e967a7bdb33..4fd71b75e666 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c | |||
@@ -224,9 +224,11 @@ static u16 netvsc_select_queue(struct net_device *ndev, struct sk_buff *skb, | |||
224 | if (nvsc_dev == NULL || ndev->real_num_tx_queues <= 1) | 224 | if (nvsc_dev == NULL || ndev->real_num_tx_queues <= 1) |
225 | return 0; | 225 | return 0; |
226 | 226 | ||
227 | if (netvsc_set_hash(&hash, skb)) | 227 | if (netvsc_set_hash(&hash, skb)) { |
228 | q_idx = nvsc_dev->send_table[hash % VRSS_SEND_TAB_SIZE] % | 228 | q_idx = nvsc_dev->send_table[hash % VRSS_SEND_TAB_SIZE] % |
229 | ndev->real_num_tx_queues; | 229 | ndev->real_num_tx_queues; |
230 | skb_set_hash(skb, hash, PKT_HASH_TYPE_L3); | ||
231 | } | ||
230 | 232 | ||
231 | return q_idx; | 233 | return q_idx; |
232 | } | 234 | } |
@@ -384,6 +386,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) | |||
384 | struct ndis_tcp_lso_info *lso_info; | 386 | struct ndis_tcp_lso_info *lso_info; |
385 | int hdr_offset; | 387 | int hdr_offset; |
386 | u32 net_trans_info; | 388 | u32 net_trans_info; |
389 | u32 hash; | ||
387 | 390 | ||
388 | 391 | ||
389 | /* We will atmost need two pages to describe the rndis | 392 | /* We will atmost need two pages to describe the rndis |
@@ -402,9 +405,8 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) | |||
402 | packet = kzalloc(sizeof(struct hv_netvsc_packet) + | 405 | packet = kzalloc(sizeof(struct hv_netvsc_packet) + |
403 | (num_data_pgs * sizeof(struct hv_page_buffer)) + | 406 | (num_data_pgs * sizeof(struct hv_page_buffer)) + |
404 | sizeof(struct rndis_message) + | 407 | sizeof(struct rndis_message) + |
405 | NDIS_VLAN_PPI_SIZE + | 408 | NDIS_VLAN_PPI_SIZE + NDIS_CSUM_PPI_SIZE + |
406 | NDIS_CSUM_PPI_SIZE + | 409 | NDIS_LSO_PPI_SIZE + NDIS_HASH_PPI_SIZE, GFP_ATOMIC); |
407 | NDIS_LSO_PPI_SIZE, GFP_ATOMIC); | ||
408 | if (!packet) { | 410 | if (!packet) { |
409 | /* out of memory, drop packet */ | 411 | /* out of memory, drop packet */ |
410 | netdev_err(net, "unable to allocate hv_netvsc_packet\n"); | 412 | netdev_err(net, "unable to allocate hv_netvsc_packet\n"); |
@@ -443,6 +445,14 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) | |||
443 | 445 | ||
444 | rndis_msg_size = RNDIS_MESSAGE_SIZE(struct rndis_packet); | 446 | rndis_msg_size = RNDIS_MESSAGE_SIZE(struct rndis_packet); |
445 | 447 | ||
448 | hash = skb_get_hash_raw(skb); | ||
449 | if (hash != 0 && net->real_num_tx_queues > 1) { | ||
450 | rndis_msg_size += NDIS_HASH_PPI_SIZE; | ||
451 | ppi = init_ppi_data(rndis_msg, NDIS_HASH_PPI_SIZE, | ||
452 | NBL_HASH_VALUE); | ||
453 | *(u32 *)((void *)ppi + ppi->ppi_offset) = hash; | ||
454 | } | ||
455 | |||
446 | if (isvlan) { | 456 | if (isvlan) { |
447 | struct ndis_pkt_8021q_info *vlan; | 457 | struct ndis_pkt_8021q_info *vlan; |
448 | 458 | ||