diff options
Diffstat (limited to 'drivers/net/hyperv')
-rw-r--r-- | drivers/net/hyperv/hyperv_net.h | 1 | ||||
-rw-r--r-- | drivers/net/hyperv/netvsc.c | 25 | ||||
-rw-r--r-- | drivers/net/hyperv/netvsc_drv.c | 10 | ||||
-rw-r--r-- | drivers/net/hyperv/rndis_filter.c | 15 |
4 files changed, 36 insertions, 15 deletions
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h index 2f48f790c9b..384ca4f4de4 100644 --- a/drivers/net/hyperv/hyperv_net.h +++ b/drivers/net/hyperv/hyperv_net.h @@ -590,6 +590,7 @@ struct nvsp_message { #define NETVSC_RECEIVE_BUFFER_ID 0xcafe +#define NETVSC_SEND_BUFFER_ID 0 #define NETVSC_PACKET_SIZE 4096 diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c index 7d76c952339..9f49c0129a7 100644 --- a/drivers/net/hyperv/netvsc.c +++ b/drivers/net/hyperv/netvsc.c @@ -161,8 +161,8 @@ static int netvsc_destroy_buf(struct netvsc_device *net_device) /* Deal with the send buffer we may have setup. * If we got a send section size, it means we received a - * SendsendBufferComplete msg (ie sent - * NvspMessage1TypeSendReceiveBuffer msg) therefore, we need + * NVSP_MSG1_TYPE_SEND_SEND_BUF_COMPLETE msg (ie sent + * NVSP_MSG1_TYPE_SEND_SEND_BUF msg) therefore, we need * to send a revoke msg here */ if (net_device->send_section_size) { @@ -172,7 +172,8 @@ static int netvsc_destroy_buf(struct netvsc_device *net_device) revoke_packet->hdr.msg_type = NVSP_MSG1_TYPE_REVOKE_SEND_BUF; - revoke_packet->msg.v1_msg.revoke_recv_buf.id = 0; + revoke_packet->msg.v1_msg.revoke_send_buf.id = + NETVSC_SEND_BUFFER_ID; ret = vmbus_sendpacket(net_device->dev->channel, revoke_packet, @@ -204,7 +205,7 @@ static int netvsc_destroy_buf(struct netvsc_device *net_device) net_device->send_buf_gpadl_handle = 0; } if (net_device->send_buf) { - /* Free up the receive buffer */ + /* Free up the send buffer */ vfree(net_device->send_buf); net_device->send_buf = NULL; } @@ -339,9 +340,9 @@ static int netvsc_init_buf(struct hv_device *device) init_packet = &net_device->channel_init_pkt; memset(init_packet, 0, sizeof(struct nvsp_message)); init_packet->hdr.msg_type = NVSP_MSG1_TYPE_SEND_SEND_BUF; - init_packet->msg.v1_msg.send_recv_buf.gpadl_handle = + init_packet->msg.v1_msg.send_send_buf.gpadl_handle = net_device->send_buf_gpadl_handle; - init_packet->msg.v1_msg.send_recv_buf.id = 0; + init_packet->msg.v1_msg.send_send_buf.id = NETVSC_SEND_BUFFER_ID; /* Send the gpadl notification request */ ret = vmbus_sendpacket(device->channel, init_packet, @@ -364,7 +365,7 @@ static int netvsc_init_buf(struct hv_device *device) netdev_err(ndev, "Unable to complete send buffer " "initialization with NetVsp - status %d\n", init_packet->msg.v1_msg. - send_recv_buf_complete.status); + send_send_buf_complete.status); ret = -EINVAL; goto cleanup; } @@ -440,7 +441,8 @@ static int negotiate_nvsp_ver(struct hv_device *device, /* NVSPv2 only: Send NDIS config */ memset(init_packet, 0, sizeof(struct nvsp_message)); init_packet->hdr.msg_type = NVSP_MSG2_TYPE_SEND_NDIS_CONFIG; - init_packet->msg.v2_msg.send_ndis_config.mtu = net_device->ndev->mtu; + init_packet->msg.v2_msg.send_ndis_config.mtu = net_device->ndev->mtu + + ETH_HLEN; init_packet->msg.v2_msg.send_ndis_config.capability.ieee8021q = 1; ret = vmbus_sendpacket(device->channel, init_packet, @@ -560,9 +562,7 @@ int netvsc_device_remove(struct hv_device *device) vmbus_close(device->channel); /* Release all resources */ - if (net_device->sub_cb_buf) - vfree(net_device->sub_cb_buf); - + vfree(net_device->sub_cb_buf); free_netvsc_device(net_device); return 0; } @@ -765,6 +765,9 @@ int netvsc_send(struct hv_device *device, out_channel = device->channel; packet->channel = out_channel; + if (out_channel->rescind) + return -ENODEV; + if (packet->page_buf_cnt) { ret = vmbus_sendpacket_pagebuffer(out_channel, packet->page_buf, diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 9e17d1a91e7..15d82eda0ba 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -193,7 +193,9 @@ static bool netvsc_set_hash(u32 *hash, struct sk_buff *skb) struct flow_keys flow; int data_len; - if (!skb_flow_dissect(skb, &flow) || flow.n_proto != htons(ETH_P_IP)) + if (!skb_flow_dissect(skb, &flow) || + !(flow.n_proto == htons(ETH_P_IP) || + flow.n_proto == htons(ETH_P_IPV6))) return false; if (flow.ip_proto == IPPROTO_TCP) @@ -550,6 +552,7 @@ do_lso: do_send: /* Start filling in the page buffers with the rndis hdr */ rndis_msg->msg_len += rndis_msg_size; + packet->total_data_buflen = rndis_msg->msg_len; packet->page_buf_cnt = init_page_array(rndis_msg, rndis_msg_size, skb, &packet->page_buf[0]); @@ -696,9 +699,10 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu) return -ENODEV; if (nvdev->nvsp_version >= NVSP_PROTOCOL_VERSION_2) - limit = NETVSC_MTU; + limit = NETVSC_MTU - ETH_HLEN; - if (mtu < 68 || mtu > limit) + /* Hyper-V hosts don't support MTU < ETH_DATA_LEN (1500) */ + if (mtu < ETH_DATA_LEN || mtu > limit) return -EINVAL; nvdev->start_remove = true; diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c index 2b86f0b6f6d..ec0c40a8f65 100644 --- a/drivers/net/hyperv/rndis_filter.c +++ b/drivers/net/hyperv/rndis_filter.c @@ -728,7 +728,8 @@ int rndis_filter_set_rss_param(struct rndis_device *rdev, int num_queue) rssp->hdr.size = sizeof(struct ndis_recv_scale_param); rssp->flag = 0; rssp->hashinfo = NDIS_HASH_FUNC_TOEPLITZ | NDIS_HASH_IPV4 | - NDIS_HASH_TCP_IPV4; + NDIS_HASH_TCP_IPV4 | NDIS_HASH_IPV6 | + NDIS_HASH_TCP_IPV6; rssp->indirect_tabsize = 4*ITAB_NUM; rssp->indirect_taboffset = sizeof(struct ndis_recv_scale_param); rssp->hashkey_size = HASH_KEYLEN; @@ -957,6 +958,9 @@ static int rndis_filter_close_device(struct rndis_device *dev) return 0; ret = rndis_filter_set_packet_filter(dev, 0); + if (ret == -ENODEV) + ret = 0; + if (ret == 0) dev->state = RNDIS_DEV_INITIALIZED; @@ -997,6 +1001,7 @@ int rndis_filter_device_add(struct hv_device *dev, int t; struct ndis_recv_scale_cap rsscap; u32 rsscap_size = sizeof(struct ndis_recv_scale_cap); + u32 mtu, size; rndis_device = get_rndis_device(); if (!rndis_device) @@ -1028,6 +1033,14 @@ int rndis_filter_device_add(struct hv_device *dev, return ret; } + /* Get the MTU from the host */ + size = sizeof(u32); + ret = rndis_filter_query_device(rndis_device, + RNDIS_OID_GEN_MAXIMUM_FRAME_SIZE, + &mtu, &size); + if (ret == 0 && size == sizeof(u32)) + net_device->ndev->mtu = mtu; + /* Get the mac address */ ret = rndis_filter_query_device_mac(rndis_device); if (ret != 0) { |