195fa0405SHaiyang Zhang /* 295fa0405SHaiyang Zhang * Copyright (c) 2009, Microsoft Corporation. 395fa0405SHaiyang Zhang * 495fa0405SHaiyang Zhang * This program is free software; you can redistribute it and/or modify it 595fa0405SHaiyang Zhang * under the terms and conditions of the GNU General Public License, 695fa0405SHaiyang Zhang * version 2, as published by the Free Software Foundation. 795fa0405SHaiyang Zhang * 895fa0405SHaiyang Zhang * This program is distributed in the hope it will be useful, but WITHOUT 995fa0405SHaiyang Zhang * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1095fa0405SHaiyang Zhang * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 1195fa0405SHaiyang Zhang * more details. 1295fa0405SHaiyang Zhang * 1395fa0405SHaiyang Zhang * You should have received a copy of the GNU General Public License along with 14adf8d3ffSJeff Kirsher * this program; if not, see <http://www.gnu.org/licenses/>. 1595fa0405SHaiyang Zhang * 1695fa0405SHaiyang Zhang * Authors: 1795fa0405SHaiyang Zhang * Haiyang Zhang <haiyangz@microsoft.com> 1895fa0405SHaiyang Zhang * Hank Janssen <hjanssen@microsoft.com> 1995fa0405SHaiyang Zhang */ 2095fa0405SHaiyang Zhang #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 2195fa0405SHaiyang Zhang 2295fa0405SHaiyang Zhang #include <linux/kernel.h> 2395fa0405SHaiyang Zhang #include <linux/sched.h> 2495fa0405SHaiyang Zhang #include <linux/wait.h> 2595fa0405SHaiyang Zhang #include <linux/mm.h> 2695fa0405SHaiyang Zhang #include <linux/delay.h> 2795fa0405SHaiyang Zhang #include <linux/io.h> 2895fa0405SHaiyang Zhang #include <linux/slab.h> 2995fa0405SHaiyang Zhang #include <linux/netdevice.h> 30f157e78dSHaiyang Zhang #include <linux/if_ether.h> 31c25aaf81SKY Srinivasan #include <asm/sync_bitops.h> 3295fa0405SHaiyang Zhang 3395fa0405SHaiyang Zhang #include "hyperv_net.h" 3495fa0405SHaiyang Zhang 3595fa0405SHaiyang Zhang 3695fa0405SHaiyang Zhang static struct netvsc_device *alloc_net_device(struct hv_device *device) 3795fa0405SHaiyang Zhang { 3895fa0405SHaiyang Zhang struct netvsc_device *net_device; 3995fa0405SHaiyang Zhang struct net_device *ndev = hv_get_drvdata(device); 4095fa0405SHaiyang Zhang 4195fa0405SHaiyang Zhang net_device = kzalloc(sizeof(struct netvsc_device), GFP_KERNEL); 4295fa0405SHaiyang Zhang if (!net_device) 4395fa0405SHaiyang Zhang return NULL; 4495fa0405SHaiyang Zhang 45f90251c8SHaiyang Zhang net_device->cb_buffer = kzalloc(NETVSC_PACKET_SIZE, GFP_KERNEL); 46f90251c8SHaiyang Zhang if (!net_device->cb_buffer) { 47f90251c8SHaiyang Zhang kfree(net_device); 48f90251c8SHaiyang Zhang return NULL; 49f90251c8SHaiyang Zhang } 50f90251c8SHaiyang Zhang 51dc5cd894SHaiyang Zhang init_waitqueue_head(&net_device->wait_drain); 524d447c9aSHaiyang Zhang net_device->start_remove = false; 5395fa0405SHaiyang Zhang net_device->destroy = false; 5495fa0405SHaiyang Zhang net_device->dev = device; 5595fa0405SHaiyang Zhang net_device->ndev = ndev; 5695fa0405SHaiyang Zhang 5795fa0405SHaiyang Zhang hv_set_drvdata(device, net_device); 5895fa0405SHaiyang Zhang return net_device; 5995fa0405SHaiyang Zhang } 6095fa0405SHaiyang Zhang 61f90251c8SHaiyang Zhang static void free_netvsc_device(struct netvsc_device *nvdev) 62f90251c8SHaiyang Zhang { 63f90251c8SHaiyang Zhang kfree(nvdev->cb_buffer); 64f90251c8SHaiyang Zhang kfree(nvdev); 65f90251c8SHaiyang Zhang } 66f90251c8SHaiyang Zhang 6795fa0405SHaiyang Zhang static struct netvsc_device *get_outbound_net_device(struct hv_device *device) 6895fa0405SHaiyang Zhang { 6995fa0405SHaiyang Zhang struct netvsc_device *net_device; 7095fa0405SHaiyang Zhang 7195fa0405SHaiyang Zhang net_device = hv_get_drvdata(device); 7295fa0405SHaiyang Zhang if (net_device && net_device->destroy) 7395fa0405SHaiyang Zhang net_device = NULL; 7495fa0405SHaiyang Zhang 7595fa0405SHaiyang Zhang return net_device; 7695fa0405SHaiyang Zhang } 7795fa0405SHaiyang Zhang 7895fa0405SHaiyang Zhang static struct netvsc_device *get_inbound_net_device(struct hv_device *device) 7995fa0405SHaiyang Zhang { 8095fa0405SHaiyang Zhang struct netvsc_device *net_device; 8195fa0405SHaiyang Zhang 8295fa0405SHaiyang Zhang net_device = hv_get_drvdata(device); 8395fa0405SHaiyang Zhang 8495fa0405SHaiyang Zhang if (!net_device) 8595fa0405SHaiyang Zhang goto get_in_err; 8695fa0405SHaiyang Zhang 8795fa0405SHaiyang Zhang if (net_device->destroy && 8895fa0405SHaiyang Zhang atomic_read(&net_device->num_outstanding_sends) == 0) 8995fa0405SHaiyang Zhang net_device = NULL; 9095fa0405SHaiyang Zhang 9195fa0405SHaiyang Zhang get_in_err: 9295fa0405SHaiyang Zhang return net_device; 9395fa0405SHaiyang Zhang } 9495fa0405SHaiyang Zhang 9595fa0405SHaiyang Zhang 96c25aaf81SKY Srinivasan static int netvsc_destroy_buf(struct netvsc_device *net_device) 9795fa0405SHaiyang Zhang { 9895fa0405SHaiyang Zhang struct nvsp_message *revoke_packet; 9995fa0405SHaiyang Zhang int ret = 0; 10095fa0405SHaiyang Zhang struct net_device *ndev = net_device->ndev; 10195fa0405SHaiyang Zhang 10295fa0405SHaiyang Zhang /* 10395fa0405SHaiyang Zhang * If we got a section count, it means we received a 10495fa0405SHaiyang Zhang * SendReceiveBufferComplete msg (ie sent 10595fa0405SHaiyang Zhang * NvspMessage1TypeSendReceiveBuffer msg) therefore, we need 10695fa0405SHaiyang Zhang * to send a revoke msg here 10795fa0405SHaiyang Zhang */ 10895fa0405SHaiyang Zhang if (net_device->recv_section_cnt) { 10995fa0405SHaiyang Zhang /* Send the revoke receive buffer */ 11095fa0405SHaiyang Zhang revoke_packet = &net_device->revoke_packet; 11195fa0405SHaiyang Zhang memset(revoke_packet, 0, sizeof(struct nvsp_message)); 11295fa0405SHaiyang Zhang 11395fa0405SHaiyang Zhang revoke_packet->hdr.msg_type = 11495fa0405SHaiyang Zhang NVSP_MSG1_TYPE_REVOKE_RECV_BUF; 11595fa0405SHaiyang Zhang revoke_packet->msg.v1_msg. 11695fa0405SHaiyang Zhang revoke_recv_buf.id = NETVSC_RECEIVE_BUFFER_ID; 11795fa0405SHaiyang Zhang 11895fa0405SHaiyang Zhang ret = vmbus_sendpacket(net_device->dev->channel, 11995fa0405SHaiyang Zhang revoke_packet, 12095fa0405SHaiyang Zhang sizeof(struct nvsp_message), 12195fa0405SHaiyang Zhang (unsigned long)revoke_packet, 12295fa0405SHaiyang Zhang VM_PKT_DATA_INBAND, 0); 12395fa0405SHaiyang Zhang /* 12495fa0405SHaiyang Zhang * If we failed here, we might as well return and 12595fa0405SHaiyang Zhang * have a leak rather than continue and a bugchk 12695fa0405SHaiyang Zhang */ 12795fa0405SHaiyang Zhang if (ret != 0) { 12895fa0405SHaiyang Zhang netdev_err(ndev, "unable to send " 12995fa0405SHaiyang Zhang "revoke receive buffer to netvsp\n"); 13095fa0405SHaiyang Zhang return ret; 13195fa0405SHaiyang Zhang } 13295fa0405SHaiyang Zhang } 13395fa0405SHaiyang Zhang 13495fa0405SHaiyang Zhang /* Teardown the gpadl on the vsp end */ 13595fa0405SHaiyang Zhang if (net_device->recv_buf_gpadl_handle) { 13695fa0405SHaiyang Zhang ret = vmbus_teardown_gpadl(net_device->dev->channel, 13795fa0405SHaiyang Zhang net_device->recv_buf_gpadl_handle); 13895fa0405SHaiyang Zhang 13995fa0405SHaiyang Zhang /* If we failed here, we might as well return and have a leak 14095fa0405SHaiyang Zhang * rather than continue and a bugchk 14195fa0405SHaiyang Zhang */ 14295fa0405SHaiyang Zhang if (ret != 0) { 14395fa0405SHaiyang Zhang netdev_err(ndev, 14495fa0405SHaiyang Zhang "unable to teardown receive buffer's gpadl\n"); 14595fa0405SHaiyang Zhang return ret; 14695fa0405SHaiyang Zhang } 14795fa0405SHaiyang Zhang net_device->recv_buf_gpadl_handle = 0; 14895fa0405SHaiyang Zhang } 14995fa0405SHaiyang Zhang 15095fa0405SHaiyang Zhang if (net_device->recv_buf) { 15195fa0405SHaiyang Zhang /* Free up the receive buffer */ 152b679ef73SHaiyang Zhang vfree(net_device->recv_buf); 15395fa0405SHaiyang Zhang net_device->recv_buf = NULL; 15495fa0405SHaiyang Zhang } 15595fa0405SHaiyang Zhang 15695fa0405SHaiyang Zhang if (net_device->recv_section) { 15795fa0405SHaiyang Zhang net_device->recv_section_cnt = 0; 15895fa0405SHaiyang Zhang kfree(net_device->recv_section); 15995fa0405SHaiyang Zhang net_device->recv_section = NULL; 16095fa0405SHaiyang Zhang } 16195fa0405SHaiyang Zhang 162c25aaf81SKY Srinivasan /* Deal with the send buffer we may have setup. 163c25aaf81SKY Srinivasan * If we got a send section size, it means we received a 164c25aaf81SKY Srinivasan * SendsendBufferComplete msg (ie sent 165c25aaf81SKY Srinivasan * NvspMessage1TypeSendReceiveBuffer msg) therefore, we need 166c25aaf81SKY Srinivasan * to send a revoke msg here 167c25aaf81SKY Srinivasan */ 168c25aaf81SKY Srinivasan if (net_device->send_section_size) { 169c25aaf81SKY Srinivasan /* Send the revoke receive buffer */ 170c25aaf81SKY Srinivasan revoke_packet = &net_device->revoke_packet; 171c25aaf81SKY Srinivasan memset(revoke_packet, 0, sizeof(struct nvsp_message)); 172c25aaf81SKY Srinivasan 173c25aaf81SKY Srinivasan revoke_packet->hdr.msg_type = 174c25aaf81SKY Srinivasan NVSP_MSG1_TYPE_REVOKE_SEND_BUF; 175c25aaf81SKY Srinivasan revoke_packet->msg.v1_msg.revoke_recv_buf.id = 0; 176c25aaf81SKY Srinivasan 177c25aaf81SKY Srinivasan ret = vmbus_sendpacket(net_device->dev->channel, 178c25aaf81SKY Srinivasan revoke_packet, 179c25aaf81SKY Srinivasan sizeof(struct nvsp_message), 180c25aaf81SKY Srinivasan (unsigned long)revoke_packet, 181c25aaf81SKY Srinivasan VM_PKT_DATA_INBAND, 0); 182c25aaf81SKY Srinivasan /* If we failed here, we might as well return and 183c25aaf81SKY Srinivasan * have a leak rather than continue and a bugchk 184c25aaf81SKY Srinivasan */ 185c25aaf81SKY Srinivasan if (ret != 0) { 186c25aaf81SKY Srinivasan netdev_err(ndev, "unable to send " 187c25aaf81SKY Srinivasan "revoke send buffer to netvsp\n"); 188c25aaf81SKY Srinivasan return ret; 189c25aaf81SKY Srinivasan } 190c25aaf81SKY Srinivasan } 191c25aaf81SKY Srinivasan /* Teardown the gpadl on the vsp end */ 192c25aaf81SKY Srinivasan if (net_device->send_buf_gpadl_handle) { 193c25aaf81SKY Srinivasan ret = vmbus_teardown_gpadl(net_device->dev->channel, 194c25aaf81SKY Srinivasan net_device->send_buf_gpadl_handle); 195c25aaf81SKY Srinivasan 196c25aaf81SKY Srinivasan /* If we failed here, we might as well return and have a leak 197c25aaf81SKY Srinivasan * rather than continue and a bugchk 198c25aaf81SKY Srinivasan */ 199c25aaf81SKY Srinivasan if (ret != 0) { 200c25aaf81SKY Srinivasan netdev_err(ndev, 201c25aaf81SKY Srinivasan "unable to teardown send buffer's gpadl\n"); 202c25aaf81SKY Srinivasan return ret; 203c25aaf81SKY Srinivasan } 2042f18423dSDave Jones net_device->send_buf_gpadl_handle = 0; 205c25aaf81SKY Srinivasan } 206c25aaf81SKY Srinivasan if (net_device->send_buf) { 207c25aaf81SKY Srinivasan /* Free up the receive buffer */ 20806b47aacSKY Srinivasan vfree(net_device->send_buf); 209c25aaf81SKY Srinivasan net_device->send_buf = NULL; 210c25aaf81SKY Srinivasan } 211c25aaf81SKY Srinivasan kfree(net_device->send_section_map); 212c25aaf81SKY Srinivasan 21395fa0405SHaiyang Zhang return ret; 21495fa0405SHaiyang Zhang } 21595fa0405SHaiyang Zhang 216c25aaf81SKY Srinivasan static int netvsc_init_buf(struct hv_device *device) 21795fa0405SHaiyang Zhang { 21895fa0405SHaiyang Zhang int ret = 0; 21995fa0405SHaiyang Zhang int t; 22095fa0405SHaiyang Zhang struct netvsc_device *net_device; 22195fa0405SHaiyang Zhang struct nvsp_message *init_packet; 22295fa0405SHaiyang Zhang struct net_device *ndev; 22395fa0405SHaiyang Zhang 22495fa0405SHaiyang Zhang net_device = get_outbound_net_device(device); 22595fa0405SHaiyang Zhang if (!net_device) 22695fa0405SHaiyang Zhang return -ENODEV; 22795fa0405SHaiyang Zhang ndev = net_device->ndev; 22895fa0405SHaiyang Zhang 229b679ef73SHaiyang Zhang net_device->recv_buf = vzalloc(net_device->recv_buf_size); 23095fa0405SHaiyang Zhang if (!net_device->recv_buf) { 23195fa0405SHaiyang Zhang netdev_err(ndev, "unable to allocate receive " 23295fa0405SHaiyang Zhang "buffer of size %d\n", net_device->recv_buf_size); 23395fa0405SHaiyang Zhang ret = -ENOMEM; 23495fa0405SHaiyang Zhang goto cleanup; 23595fa0405SHaiyang Zhang } 23695fa0405SHaiyang Zhang 23795fa0405SHaiyang Zhang /* 23895fa0405SHaiyang Zhang * Establish the gpadl handle for this buffer on this 23995fa0405SHaiyang Zhang * channel. Note: This call uses the vmbus connection rather 24095fa0405SHaiyang Zhang * than the channel to establish the gpadl handle. 24195fa0405SHaiyang Zhang */ 24295fa0405SHaiyang Zhang ret = vmbus_establish_gpadl(device->channel, net_device->recv_buf, 24395fa0405SHaiyang Zhang net_device->recv_buf_size, 24495fa0405SHaiyang Zhang &net_device->recv_buf_gpadl_handle); 24595fa0405SHaiyang Zhang if (ret != 0) { 24695fa0405SHaiyang Zhang netdev_err(ndev, 24795fa0405SHaiyang Zhang "unable to establish receive buffer's gpadl\n"); 24895fa0405SHaiyang Zhang goto cleanup; 24995fa0405SHaiyang Zhang } 25095fa0405SHaiyang Zhang 25195fa0405SHaiyang Zhang 25295fa0405SHaiyang Zhang /* Notify the NetVsp of the gpadl handle */ 25395fa0405SHaiyang Zhang init_packet = &net_device->channel_init_pkt; 25495fa0405SHaiyang Zhang 25595fa0405SHaiyang Zhang memset(init_packet, 0, sizeof(struct nvsp_message)); 25695fa0405SHaiyang Zhang 25795fa0405SHaiyang Zhang init_packet->hdr.msg_type = NVSP_MSG1_TYPE_SEND_RECV_BUF; 25895fa0405SHaiyang Zhang init_packet->msg.v1_msg.send_recv_buf. 25995fa0405SHaiyang Zhang gpadl_handle = net_device->recv_buf_gpadl_handle; 26095fa0405SHaiyang Zhang init_packet->msg.v1_msg. 26195fa0405SHaiyang Zhang send_recv_buf.id = NETVSC_RECEIVE_BUFFER_ID; 26295fa0405SHaiyang Zhang 26395fa0405SHaiyang Zhang /* Send the gpadl notification request */ 26495fa0405SHaiyang Zhang ret = vmbus_sendpacket(device->channel, init_packet, 26595fa0405SHaiyang Zhang sizeof(struct nvsp_message), 26695fa0405SHaiyang Zhang (unsigned long)init_packet, 26795fa0405SHaiyang Zhang VM_PKT_DATA_INBAND, 26895fa0405SHaiyang Zhang VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); 26995fa0405SHaiyang Zhang if (ret != 0) { 27095fa0405SHaiyang Zhang netdev_err(ndev, 27195fa0405SHaiyang Zhang "unable to send receive buffer's gpadl to netvsp\n"); 27295fa0405SHaiyang Zhang goto cleanup; 27395fa0405SHaiyang Zhang } 27495fa0405SHaiyang Zhang 27595fa0405SHaiyang Zhang t = wait_for_completion_timeout(&net_device->channel_init_wait, 5*HZ); 27695fa0405SHaiyang Zhang BUG_ON(t == 0); 27795fa0405SHaiyang Zhang 27895fa0405SHaiyang Zhang 27995fa0405SHaiyang Zhang /* Check the response */ 28095fa0405SHaiyang Zhang if (init_packet->msg.v1_msg. 28195fa0405SHaiyang Zhang send_recv_buf_complete.status != NVSP_STAT_SUCCESS) { 28295fa0405SHaiyang Zhang netdev_err(ndev, "Unable to complete receive buffer " 28395fa0405SHaiyang Zhang "initialization with NetVsp - status %d\n", 28495fa0405SHaiyang Zhang init_packet->msg.v1_msg. 28595fa0405SHaiyang Zhang send_recv_buf_complete.status); 28695fa0405SHaiyang Zhang ret = -EINVAL; 28795fa0405SHaiyang Zhang goto cleanup; 28895fa0405SHaiyang Zhang } 28995fa0405SHaiyang Zhang 29095fa0405SHaiyang Zhang /* Parse the response */ 29195fa0405SHaiyang Zhang 29295fa0405SHaiyang Zhang net_device->recv_section_cnt = init_packet->msg. 29395fa0405SHaiyang Zhang v1_msg.send_recv_buf_complete.num_sections; 29495fa0405SHaiyang Zhang 295c1813200SHaiyang Zhang net_device->recv_section = kmemdup( 296c1813200SHaiyang Zhang init_packet->msg.v1_msg.send_recv_buf_complete.sections, 297c1813200SHaiyang Zhang net_device->recv_section_cnt * 298c1813200SHaiyang Zhang sizeof(struct nvsp_1_receive_buffer_section), 29995fa0405SHaiyang Zhang GFP_KERNEL); 30095fa0405SHaiyang Zhang if (net_device->recv_section == NULL) { 30195fa0405SHaiyang Zhang ret = -EINVAL; 30295fa0405SHaiyang Zhang goto cleanup; 30395fa0405SHaiyang Zhang } 30495fa0405SHaiyang Zhang 30595fa0405SHaiyang Zhang /* 30695fa0405SHaiyang Zhang * For 1st release, there should only be 1 section that represents the 30795fa0405SHaiyang Zhang * entire receive buffer 30895fa0405SHaiyang Zhang */ 30995fa0405SHaiyang Zhang if (net_device->recv_section_cnt != 1 || 31095fa0405SHaiyang Zhang net_device->recv_section->offset != 0) { 31195fa0405SHaiyang Zhang ret = -EINVAL; 31295fa0405SHaiyang Zhang goto cleanup; 31395fa0405SHaiyang Zhang } 31495fa0405SHaiyang Zhang 315c25aaf81SKY Srinivasan /* Now setup the send buffer. 316c25aaf81SKY Srinivasan */ 31706b47aacSKY Srinivasan net_device->send_buf = vzalloc(net_device->send_buf_size); 318c25aaf81SKY Srinivasan if (!net_device->send_buf) { 319c25aaf81SKY Srinivasan netdev_err(ndev, "unable to allocate send " 320c25aaf81SKY Srinivasan "buffer of size %d\n", net_device->send_buf_size); 321c25aaf81SKY Srinivasan ret = -ENOMEM; 322c25aaf81SKY Srinivasan goto cleanup; 323c25aaf81SKY Srinivasan } 324c25aaf81SKY Srinivasan 325c25aaf81SKY Srinivasan /* Establish the gpadl handle for this buffer on this 326c25aaf81SKY Srinivasan * channel. Note: This call uses the vmbus connection rather 327c25aaf81SKY Srinivasan * than the channel to establish the gpadl handle. 328c25aaf81SKY Srinivasan */ 329c25aaf81SKY Srinivasan ret = vmbus_establish_gpadl(device->channel, net_device->send_buf, 330c25aaf81SKY Srinivasan net_device->send_buf_size, 331c25aaf81SKY Srinivasan &net_device->send_buf_gpadl_handle); 332c25aaf81SKY Srinivasan if (ret != 0) { 333c25aaf81SKY Srinivasan netdev_err(ndev, 334c25aaf81SKY Srinivasan "unable to establish send buffer's gpadl\n"); 335c25aaf81SKY Srinivasan goto cleanup; 336c25aaf81SKY Srinivasan } 337c25aaf81SKY Srinivasan 338c25aaf81SKY Srinivasan /* Notify the NetVsp of the gpadl handle */ 339c25aaf81SKY Srinivasan init_packet = &net_device->channel_init_pkt; 340c25aaf81SKY Srinivasan memset(init_packet, 0, sizeof(struct nvsp_message)); 341c25aaf81SKY Srinivasan init_packet->hdr.msg_type = NVSP_MSG1_TYPE_SEND_SEND_BUF; 342c25aaf81SKY Srinivasan init_packet->msg.v1_msg.send_recv_buf.gpadl_handle = 343c25aaf81SKY Srinivasan net_device->send_buf_gpadl_handle; 344c25aaf81SKY Srinivasan init_packet->msg.v1_msg.send_recv_buf.id = 0; 345c25aaf81SKY Srinivasan 346c25aaf81SKY Srinivasan /* Send the gpadl notification request */ 347c25aaf81SKY Srinivasan ret = vmbus_sendpacket(device->channel, init_packet, 348c25aaf81SKY Srinivasan sizeof(struct nvsp_message), 349c25aaf81SKY Srinivasan (unsigned long)init_packet, 350c25aaf81SKY Srinivasan VM_PKT_DATA_INBAND, 351c25aaf81SKY Srinivasan VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); 352c25aaf81SKY Srinivasan if (ret != 0) { 353c25aaf81SKY Srinivasan netdev_err(ndev, 354c25aaf81SKY Srinivasan "unable to send send buffer's gpadl to netvsp\n"); 355c25aaf81SKY Srinivasan goto cleanup; 356c25aaf81SKY Srinivasan } 357c25aaf81SKY Srinivasan 358c25aaf81SKY Srinivasan t = wait_for_completion_timeout(&net_device->channel_init_wait, 5*HZ); 359c25aaf81SKY Srinivasan BUG_ON(t == 0); 360c25aaf81SKY Srinivasan 361c25aaf81SKY Srinivasan /* Check the response */ 362c25aaf81SKY Srinivasan if (init_packet->msg.v1_msg. 363c25aaf81SKY Srinivasan send_send_buf_complete.status != NVSP_STAT_SUCCESS) { 364c25aaf81SKY Srinivasan netdev_err(ndev, "Unable to complete send buffer " 365c25aaf81SKY Srinivasan "initialization with NetVsp - status %d\n", 366c25aaf81SKY Srinivasan init_packet->msg.v1_msg. 367c25aaf81SKY Srinivasan send_recv_buf_complete.status); 368c25aaf81SKY Srinivasan ret = -EINVAL; 369c25aaf81SKY Srinivasan goto cleanup; 370c25aaf81SKY Srinivasan } 371c25aaf81SKY Srinivasan 372c25aaf81SKY Srinivasan /* Parse the response */ 373c25aaf81SKY Srinivasan net_device->send_section_size = init_packet->msg. 374c25aaf81SKY Srinivasan v1_msg.send_send_buf_complete.section_size; 375c25aaf81SKY Srinivasan 376c25aaf81SKY Srinivasan /* Section count is simply the size divided by the section size. 377c25aaf81SKY Srinivasan */ 378c25aaf81SKY Srinivasan net_device->send_section_cnt = 379c25aaf81SKY Srinivasan net_device->send_buf_size/net_device->send_section_size; 380c25aaf81SKY Srinivasan 381c25aaf81SKY Srinivasan dev_info(&device->device, "Send section size: %d, Section count:%d\n", 382c25aaf81SKY Srinivasan net_device->send_section_size, net_device->send_section_cnt); 383c25aaf81SKY Srinivasan 384c25aaf81SKY Srinivasan /* Setup state for managing the send buffer. */ 385c25aaf81SKY Srinivasan net_device->map_words = DIV_ROUND_UP(net_device->send_section_cnt, 386c25aaf81SKY Srinivasan BITS_PER_LONG); 387c25aaf81SKY Srinivasan 388c25aaf81SKY Srinivasan net_device->send_section_map = 389c25aaf81SKY Srinivasan kzalloc(net_device->map_words * sizeof(ulong), GFP_KERNEL); 390dd1d3f8fSWei Yongjun if (net_device->send_section_map == NULL) { 391dd1d3f8fSWei Yongjun ret = -ENOMEM; 392c25aaf81SKY Srinivasan goto cleanup; 393dd1d3f8fSWei Yongjun } 394c25aaf81SKY Srinivasan 39595fa0405SHaiyang Zhang goto exit; 39695fa0405SHaiyang Zhang 39795fa0405SHaiyang Zhang cleanup: 398c25aaf81SKY Srinivasan netvsc_destroy_buf(net_device); 39995fa0405SHaiyang Zhang 40095fa0405SHaiyang Zhang exit: 40195fa0405SHaiyang Zhang return ret; 40295fa0405SHaiyang Zhang } 40395fa0405SHaiyang Zhang 40495fa0405SHaiyang Zhang 405f157e78dSHaiyang Zhang /* Negotiate NVSP protocol version */ 406f157e78dSHaiyang Zhang static int negotiate_nvsp_ver(struct hv_device *device, 407f157e78dSHaiyang Zhang struct netvsc_device *net_device, 408f157e78dSHaiyang Zhang struct nvsp_message *init_packet, 409f157e78dSHaiyang Zhang u32 nvsp_ver) 41095fa0405SHaiyang Zhang { 41195fa0405SHaiyang Zhang int ret, t; 412f157e78dSHaiyang Zhang 413f157e78dSHaiyang Zhang memset(init_packet, 0, sizeof(struct nvsp_message)); 414f157e78dSHaiyang Zhang init_packet->hdr.msg_type = NVSP_MSG_TYPE_INIT; 415f157e78dSHaiyang Zhang init_packet->msg.init_msg.init.min_protocol_ver = nvsp_ver; 416f157e78dSHaiyang Zhang init_packet->msg.init_msg.init.max_protocol_ver = nvsp_ver; 417f157e78dSHaiyang Zhang 418f157e78dSHaiyang Zhang /* Send the init request */ 419f157e78dSHaiyang Zhang ret = vmbus_sendpacket(device->channel, init_packet, 420f157e78dSHaiyang Zhang sizeof(struct nvsp_message), 421f157e78dSHaiyang Zhang (unsigned long)init_packet, 422f157e78dSHaiyang Zhang VM_PKT_DATA_INBAND, 423f157e78dSHaiyang Zhang VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); 424f157e78dSHaiyang Zhang 425f157e78dSHaiyang Zhang if (ret != 0) 426f157e78dSHaiyang Zhang return ret; 427f157e78dSHaiyang Zhang 428f157e78dSHaiyang Zhang t = wait_for_completion_timeout(&net_device->channel_init_wait, 5*HZ); 429f157e78dSHaiyang Zhang 430f157e78dSHaiyang Zhang if (t == 0) 431f157e78dSHaiyang Zhang return -ETIMEDOUT; 432f157e78dSHaiyang Zhang 433f157e78dSHaiyang Zhang if (init_packet->msg.init_msg.init_complete.status != 434f157e78dSHaiyang Zhang NVSP_STAT_SUCCESS) 435f157e78dSHaiyang Zhang return -EINVAL; 436f157e78dSHaiyang Zhang 437a1eabb01SHaiyang Zhang if (nvsp_ver == NVSP_PROTOCOL_VERSION_1) 438f157e78dSHaiyang Zhang return 0; 439f157e78dSHaiyang Zhang 440f157e78dSHaiyang Zhang /* NVSPv2 only: Send NDIS config */ 441f157e78dSHaiyang Zhang memset(init_packet, 0, sizeof(struct nvsp_message)); 442f157e78dSHaiyang Zhang init_packet->hdr.msg_type = NVSP_MSG2_TYPE_SEND_NDIS_CONFIG; 4434d3c9d37SHaiyang Zhang init_packet->msg.v2_msg.send_ndis_config.mtu = net_device->ndev->mtu + 4444d3c9d37SHaiyang Zhang ETH_HLEN; 4451f5f3a75SHaiyang Zhang init_packet->msg.v2_msg.send_ndis_config.capability.ieee8021q = 1; 446f157e78dSHaiyang Zhang 447f157e78dSHaiyang Zhang ret = vmbus_sendpacket(device->channel, init_packet, 448f157e78dSHaiyang Zhang sizeof(struct nvsp_message), 449f157e78dSHaiyang Zhang (unsigned long)init_packet, 450f157e78dSHaiyang Zhang VM_PKT_DATA_INBAND, 0); 451f157e78dSHaiyang Zhang 452f157e78dSHaiyang Zhang return ret; 453f157e78dSHaiyang Zhang } 454f157e78dSHaiyang Zhang 455f157e78dSHaiyang Zhang static int netvsc_connect_vsp(struct hv_device *device) 456f157e78dSHaiyang Zhang { 457f157e78dSHaiyang Zhang int ret; 45895fa0405SHaiyang Zhang struct netvsc_device *net_device; 45995fa0405SHaiyang Zhang struct nvsp_message *init_packet; 46095fa0405SHaiyang Zhang int ndis_version; 46195fa0405SHaiyang Zhang struct net_device *ndev; 462a1eabb01SHaiyang Zhang u32 ver_list[] = { NVSP_PROTOCOL_VERSION_1, NVSP_PROTOCOL_VERSION_2, 463a1eabb01SHaiyang Zhang NVSP_PROTOCOL_VERSION_4, NVSP_PROTOCOL_VERSION_5 }; 464a1eabb01SHaiyang Zhang int i, num_ver = 4; /* number of different NVSP versions */ 46595fa0405SHaiyang Zhang 46695fa0405SHaiyang Zhang net_device = get_outbound_net_device(device); 46795fa0405SHaiyang Zhang if (!net_device) 46895fa0405SHaiyang Zhang return -ENODEV; 46995fa0405SHaiyang Zhang ndev = net_device->ndev; 47095fa0405SHaiyang Zhang 47195fa0405SHaiyang Zhang init_packet = &net_device->channel_init_pkt; 47295fa0405SHaiyang Zhang 473f157e78dSHaiyang Zhang /* Negotiate the latest NVSP protocol supported */ 474a1eabb01SHaiyang Zhang for (i = num_ver - 1; i >= 0; i--) 475f157e78dSHaiyang Zhang if (negotiate_nvsp_ver(device, net_device, init_packet, 476a1eabb01SHaiyang Zhang ver_list[i]) == 0) { 477a1eabb01SHaiyang Zhang net_device->nvsp_version = ver_list[i]; 478a1eabb01SHaiyang Zhang break; 479a1eabb01SHaiyang Zhang } 480a1eabb01SHaiyang Zhang 481a1eabb01SHaiyang Zhang if (i < 0) { 48295fa0405SHaiyang Zhang ret = -EPROTO; 48395fa0405SHaiyang Zhang goto cleanup; 48495fa0405SHaiyang Zhang } 485f157e78dSHaiyang Zhang 486f157e78dSHaiyang Zhang pr_debug("Negotiated NVSP version:%x\n", net_device->nvsp_version); 487f157e78dSHaiyang Zhang 48895fa0405SHaiyang Zhang /* Send the ndis version */ 48995fa0405SHaiyang Zhang memset(init_packet, 0, sizeof(struct nvsp_message)); 49095fa0405SHaiyang Zhang 491a1eabb01SHaiyang Zhang if (net_device->nvsp_version <= NVSP_PROTOCOL_VERSION_4) 4921f73db49SKY Srinivasan ndis_version = 0x00060001; 493a1eabb01SHaiyang Zhang else 494a1eabb01SHaiyang Zhang ndis_version = 0x0006001e; 49595fa0405SHaiyang Zhang 49695fa0405SHaiyang Zhang init_packet->hdr.msg_type = NVSP_MSG1_TYPE_SEND_NDIS_VER; 49795fa0405SHaiyang Zhang init_packet->msg.v1_msg. 49895fa0405SHaiyang Zhang send_ndis_ver.ndis_major_ver = 49995fa0405SHaiyang Zhang (ndis_version & 0xFFFF0000) >> 16; 50095fa0405SHaiyang Zhang init_packet->msg.v1_msg. 50195fa0405SHaiyang Zhang send_ndis_ver.ndis_minor_ver = 50295fa0405SHaiyang Zhang ndis_version & 0xFFFF; 50395fa0405SHaiyang Zhang 50495fa0405SHaiyang Zhang /* Send the init request */ 50595fa0405SHaiyang Zhang ret = vmbus_sendpacket(device->channel, init_packet, 50695fa0405SHaiyang Zhang sizeof(struct nvsp_message), 50795fa0405SHaiyang Zhang (unsigned long)init_packet, 50895fa0405SHaiyang Zhang VM_PKT_DATA_INBAND, 0); 50995fa0405SHaiyang Zhang if (ret != 0) 51095fa0405SHaiyang Zhang goto cleanup; 51195fa0405SHaiyang Zhang 51295fa0405SHaiyang Zhang /* Post the big receive buffer to NetVSP */ 51399d3016dSHaiyang Zhang if (net_device->nvsp_version <= NVSP_PROTOCOL_VERSION_2) 51499d3016dSHaiyang Zhang net_device->recv_buf_size = NETVSC_RECEIVE_BUFFER_SIZE_LEGACY; 51599d3016dSHaiyang Zhang else 51699d3016dSHaiyang Zhang net_device->recv_buf_size = NETVSC_RECEIVE_BUFFER_SIZE; 517c25aaf81SKY Srinivasan net_device->send_buf_size = NETVSC_SEND_BUFFER_SIZE; 51899d3016dSHaiyang Zhang 519c25aaf81SKY Srinivasan ret = netvsc_init_buf(device); 52095fa0405SHaiyang Zhang 52195fa0405SHaiyang Zhang cleanup: 52295fa0405SHaiyang Zhang return ret; 52395fa0405SHaiyang Zhang } 52495fa0405SHaiyang Zhang 52595fa0405SHaiyang Zhang static void netvsc_disconnect_vsp(struct netvsc_device *net_device) 52695fa0405SHaiyang Zhang { 527c25aaf81SKY Srinivasan netvsc_destroy_buf(net_device); 52895fa0405SHaiyang Zhang } 52995fa0405SHaiyang Zhang 53095fa0405SHaiyang Zhang /* 53195fa0405SHaiyang Zhang * netvsc_device_remove - Callback when the root bus device is removed 53295fa0405SHaiyang Zhang */ 53395fa0405SHaiyang Zhang int netvsc_device_remove(struct hv_device *device) 53495fa0405SHaiyang Zhang { 53595fa0405SHaiyang Zhang struct netvsc_device *net_device; 53695fa0405SHaiyang Zhang unsigned long flags; 53795fa0405SHaiyang Zhang 53895fa0405SHaiyang Zhang net_device = hv_get_drvdata(device); 53995fa0405SHaiyang Zhang 54095fa0405SHaiyang Zhang netvsc_disconnect_vsp(net_device); 54195fa0405SHaiyang Zhang 54295fa0405SHaiyang Zhang /* 54395fa0405SHaiyang Zhang * Since we have already drained, we don't need to busy wait 54495fa0405SHaiyang Zhang * as was done in final_release_stor_device() 54595fa0405SHaiyang Zhang * Note that we cannot set the ext pointer to NULL until 54695fa0405SHaiyang Zhang * we have drained - to drain the outgoing packets, we need to 54795fa0405SHaiyang Zhang * allow incoming packets. 54895fa0405SHaiyang Zhang */ 54995fa0405SHaiyang Zhang 55095fa0405SHaiyang Zhang spin_lock_irqsave(&device->channel->inbound_lock, flags); 55195fa0405SHaiyang Zhang hv_set_drvdata(device, NULL); 55295fa0405SHaiyang Zhang spin_unlock_irqrestore(&device->channel->inbound_lock, flags); 55395fa0405SHaiyang Zhang 55495fa0405SHaiyang Zhang /* 55595fa0405SHaiyang Zhang * At this point, no one should be accessing net_device 55695fa0405SHaiyang Zhang * except in here 55795fa0405SHaiyang Zhang */ 55895fa0405SHaiyang Zhang dev_notice(&device->device, "net device safe to remove\n"); 55995fa0405SHaiyang Zhang 56095fa0405SHaiyang Zhang /* Now, we can close the channel safely */ 56195fa0405SHaiyang Zhang vmbus_close(device->channel); 56295fa0405SHaiyang Zhang 56395fa0405SHaiyang Zhang /* Release all resources */ 5645b54dac8SHaiyang Zhang if (net_device->sub_cb_buf) 5655b54dac8SHaiyang Zhang vfree(net_device->sub_cb_buf); 5665b54dac8SHaiyang Zhang 567f90251c8SHaiyang Zhang free_netvsc_device(net_device); 56895fa0405SHaiyang Zhang return 0; 56995fa0405SHaiyang Zhang } 57095fa0405SHaiyang Zhang 57133be96e4SHaiyang Zhang 57233be96e4SHaiyang Zhang #define RING_AVAIL_PERCENT_HIWATER 20 57333be96e4SHaiyang Zhang #define RING_AVAIL_PERCENT_LOWATER 10 57433be96e4SHaiyang Zhang 57533be96e4SHaiyang Zhang /* 57633be96e4SHaiyang Zhang * Get the percentage of available bytes to write in the ring. 57733be96e4SHaiyang Zhang * The return value is in range from 0 to 100. 57833be96e4SHaiyang Zhang */ 57933be96e4SHaiyang Zhang static inline u32 hv_ringbuf_avail_percent( 58033be96e4SHaiyang Zhang struct hv_ring_buffer_info *ring_info) 58133be96e4SHaiyang Zhang { 58233be96e4SHaiyang Zhang u32 avail_read, avail_write; 58333be96e4SHaiyang Zhang 58433be96e4SHaiyang Zhang hv_get_ringbuffer_availbytes(ring_info, &avail_read, &avail_write); 58533be96e4SHaiyang Zhang 58633be96e4SHaiyang Zhang return avail_write * 100 / ring_info->ring_datasize; 58733be96e4SHaiyang Zhang } 58833be96e4SHaiyang Zhang 589c25aaf81SKY Srinivasan static inline void netvsc_free_send_slot(struct netvsc_device *net_device, 590c25aaf81SKY Srinivasan u32 index) 591c25aaf81SKY Srinivasan { 592c25aaf81SKY Srinivasan sync_change_bit(index, net_device->send_section_map); 593c25aaf81SKY Srinivasan } 594c25aaf81SKY Srinivasan 59597c1723aSKY Srinivasan static void netvsc_send_completion(struct netvsc_device *net_device, 59697c1723aSKY Srinivasan struct hv_device *device, 59795fa0405SHaiyang Zhang struct vmpacket_descriptor *packet) 59895fa0405SHaiyang Zhang { 59995fa0405SHaiyang Zhang struct nvsp_message *nvsp_packet; 60095fa0405SHaiyang Zhang struct hv_netvsc_packet *nvsc_packet; 60195fa0405SHaiyang Zhang struct net_device *ndev; 602c25aaf81SKY Srinivasan u32 send_index; 60395fa0405SHaiyang Zhang 60495fa0405SHaiyang Zhang ndev = net_device->ndev; 60595fa0405SHaiyang Zhang 60695fa0405SHaiyang Zhang nvsp_packet = (struct nvsp_message *)((unsigned long)packet + 60795fa0405SHaiyang Zhang (packet->offset8 << 3)); 60895fa0405SHaiyang Zhang 60995fa0405SHaiyang Zhang if ((nvsp_packet->hdr.msg_type == NVSP_MSG_TYPE_INIT_COMPLETE) || 61095fa0405SHaiyang Zhang (nvsp_packet->hdr.msg_type == 61195fa0405SHaiyang Zhang NVSP_MSG1_TYPE_SEND_RECV_BUF_COMPLETE) || 61295fa0405SHaiyang Zhang (nvsp_packet->hdr.msg_type == 6135b54dac8SHaiyang Zhang NVSP_MSG1_TYPE_SEND_SEND_BUF_COMPLETE) || 6145b54dac8SHaiyang Zhang (nvsp_packet->hdr.msg_type == 6155b54dac8SHaiyang Zhang NVSP_MSG5_TYPE_SUBCHANNEL)) { 61695fa0405SHaiyang Zhang /* Copy the response back */ 61795fa0405SHaiyang Zhang memcpy(&net_device->channel_init_pkt, nvsp_packet, 61895fa0405SHaiyang Zhang sizeof(struct nvsp_message)); 61995fa0405SHaiyang Zhang complete(&net_device->channel_init_wait); 62095fa0405SHaiyang Zhang } else if (nvsp_packet->hdr.msg_type == 62195fa0405SHaiyang Zhang NVSP_MSG1_TYPE_SEND_RNDIS_PKT_COMPLETE) { 62233be96e4SHaiyang Zhang int num_outstanding_sends; 6235b54dac8SHaiyang Zhang u16 q_idx = 0; 6245b54dac8SHaiyang Zhang struct vmbus_channel *channel = device->channel; 6255b54dac8SHaiyang Zhang int queue_sends; 62633be96e4SHaiyang Zhang 62795fa0405SHaiyang Zhang /* Get the send context */ 62895fa0405SHaiyang Zhang nvsc_packet = (struct hv_netvsc_packet *)(unsigned long) 62995fa0405SHaiyang Zhang packet->trans_id; 63095fa0405SHaiyang Zhang 63195fa0405SHaiyang Zhang /* Notify the layer above us */ 6325b54dac8SHaiyang Zhang if (nvsc_packet) { 633c25aaf81SKY Srinivasan send_index = nvsc_packet->send_buf_index; 634c25aaf81SKY Srinivasan if (send_index != NETVSC_INVALID_INDEX) 635c25aaf81SKY Srinivasan netvsc_free_send_slot(net_device, send_index); 6365b54dac8SHaiyang Zhang q_idx = nvsc_packet->q_idx; 6375b54dac8SHaiyang Zhang channel = nvsc_packet->channel; 638893f6627SHaiyang Zhang nvsc_packet->send_completion(nvsc_packet-> 639f1ea3cd7SHaiyang Zhang send_completion_ctx); 6405b54dac8SHaiyang Zhang } 64195fa0405SHaiyang Zhang 64233be96e4SHaiyang Zhang num_outstanding_sends = 64333be96e4SHaiyang Zhang atomic_dec_return(&net_device->num_outstanding_sends); 6445b54dac8SHaiyang Zhang queue_sends = atomic_dec_return(&net_device-> 6455b54dac8SHaiyang Zhang queue_sends[q_idx]); 6461d06825bSHaiyang Zhang 647dc5cd894SHaiyang Zhang if (net_device->destroy && num_outstanding_sends == 0) 648dc5cd894SHaiyang Zhang wake_up(&net_device->wait_drain); 649dc5cd894SHaiyang Zhang 6505b54dac8SHaiyang Zhang if (netif_tx_queue_stopped(netdev_get_tx_queue(ndev, q_idx)) && 6515b54dac8SHaiyang Zhang !net_device->start_remove && 6525b54dac8SHaiyang Zhang (hv_ringbuf_avail_percent(&channel->outbound) > 6535b54dac8SHaiyang Zhang RING_AVAIL_PERCENT_HIWATER || queue_sends < 1)) 6545b54dac8SHaiyang Zhang netif_tx_wake_queue(netdev_get_tx_queue( 6555b54dac8SHaiyang Zhang ndev, q_idx)); 65695fa0405SHaiyang Zhang } else { 65795fa0405SHaiyang Zhang netdev_err(ndev, "Unknown send completion packet type- " 65895fa0405SHaiyang Zhang "%d received!!\n", nvsp_packet->hdr.msg_type); 65995fa0405SHaiyang Zhang } 66095fa0405SHaiyang Zhang 66195fa0405SHaiyang Zhang } 66295fa0405SHaiyang Zhang 663c25aaf81SKY Srinivasan static u32 netvsc_get_next_send_section(struct netvsc_device *net_device) 664c25aaf81SKY Srinivasan { 665c25aaf81SKY Srinivasan unsigned long index; 666c25aaf81SKY Srinivasan u32 max_words = net_device->map_words; 667c25aaf81SKY Srinivasan unsigned long *map_addr = (unsigned long *)net_device->send_section_map; 668c25aaf81SKY Srinivasan u32 section_cnt = net_device->send_section_cnt; 669c25aaf81SKY Srinivasan int ret_val = NETVSC_INVALID_INDEX; 670c25aaf81SKY Srinivasan int i; 671c25aaf81SKY Srinivasan int prev_val; 672c25aaf81SKY Srinivasan 673c25aaf81SKY Srinivasan for (i = 0; i < max_words; i++) { 674c25aaf81SKY Srinivasan if (!~(map_addr[i])) 675c25aaf81SKY Srinivasan continue; 676c25aaf81SKY Srinivasan index = ffz(map_addr[i]); 677c25aaf81SKY Srinivasan prev_val = sync_test_and_set_bit(index, &map_addr[i]); 678c25aaf81SKY Srinivasan if (prev_val) 679c25aaf81SKY Srinivasan continue; 680c25aaf81SKY Srinivasan if ((index + (i * BITS_PER_LONG)) >= section_cnt) 681c25aaf81SKY Srinivasan break; 682c25aaf81SKY Srinivasan ret_val = (index + (i * BITS_PER_LONG)); 683c25aaf81SKY Srinivasan break; 684c25aaf81SKY Srinivasan } 685c25aaf81SKY Srinivasan return ret_val; 686c25aaf81SKY Srinivasan } 687c25aaf81SKY Srinivasan 688c25aaf81SKY Srinivasan u32 netvsc_copy_to_send_buf(struct netvsc_device *net_device, 689c25aaf81SKY Srinivasan unsigned int section_index, 690c25aaf81SKY Srinivasan struct hv_netvsc_packet *packet) 691c25aaf81SKY Srinivasan { 692c25aaf81SKY Srinivasan char *start = net_device->send_buf; 693c25aaf81SKY Srinivasan char *dest = (start + (section_index * net_device->send_section_size)); 694c25aaf81SKY Srinivasan int i; 695c25aaf81SKY Srinivasan u32 msg_size = 0; 696c25aaf81SKY Srinivasan 697c25aaf81SKY Srinivasan for (i = 0; i < packet->page_buf_cnt; i++) { 698c25aaf81SKY Srinivasan char *src = phys_to_virt(packet->page_buf[i].pfn << PAGE_SHIFT); 699c25aaf81SKY Srinivasan u32 offset = packet->page_buf[i].offset; 700c25aaf81SKY Srinivasan u32 len = packet->page_buf[i].len; 701c25aaf81SKY Srinivasan 702c25aaf81SKY Srinivasan memcpy(dest, (src + offset), len); 703c25aaf81SKY Srinivasan msg_size += len; 704c25aaf81SKY Srinivasan dest += len; 705c25aaf81SKY Srinivasan } 706c25aaf81SKY Srinivasan return msg_size; 707c25aaf81SKY Srinivasan } 708c25aaf81SKY Srinivasan 70995fa0405SHaiyang Zhang int netvsc_send(struct hv_device *device, 71095fa0405SHaiyang Zhang struct hv_netvsc_packet *packet) 71195fa0405SHaiyang Zhang { 71295fa0405SHaiyang Zhang struct netvsc_device *net_device; 71395fa0405SHaiyang Zhang int ret = 0; 71495fa0405SHaiyang Zhang struct nvsp_message sendMessage; 71595fa0405SHaiyang Zhang struct net_device *ndev; 7165b54dac8SHaiyang Zhang struct vmbus_channel *out_channel = NULL; 717f1ea3cd7SHaiyang Zhang u64 req_id; 718c25aaf81SKY Srinivasan unsigned int section_index = NETVSC_INVALID_INDEX; 719c25aaf81SKY Srinivasan u32 msg_size = 0; 720c25aaf81SKY Srinivasan struct sk_buff *skb; 7213a67c9ccSKY Srinivasan u16 q_idx = packet->q_idx; 722c25aaf81SKY Srinivasan 72395fa0405SHaiyang Zhang 72495fa0405SHaiyang Zhang net_device = get_outbound_net_device(device); 72595fa0405SHaiyang Zhang if (!net_device) 72695fa0405SHaiyang Zhang return -ENODEV; 72795fa0405SHaiyang Zhang ndev = net_device->ndev; 72895fa0405SHaiyang Zhang 72995fa0405SHaiyang Zhang sendMessage.hdr.msg_type = NVSP_MSG1_TYPE_SEND_RNDIS_PKT; 73095fa0405SHaiyang Zhang if (packet->is_data_pkt) { 73195fa0405SHaiyang Zhang /* 0 is RMC_DATA; */ 73295fa0405SHaiyang Zhang sendMessage.msg.v1_msg.send_rndis_pkt.channel_type = 0; 73395fa0405SHaiyang Zhang } else { 73495fa0405SHaiyang Zhang /* 1 is RMC_CONTROL; */ 73595fa0405SHaiyang Zhang sendMessage.msg.v1_msg.send_rndis_pkt.channel_type = 1; 73695fa0405SHaiyang Zhang } 73795fa0405SHaiyang Zhang 738c25aaf81SKY Srinivasan /* Attempt to send via sendbuf */ 739c25aaf81SKY Srinivasan if (packet->total_data_buflen < net_device->send_section_size) { 740c25aaf81SKY Srinivasan section_index = netvsc_get_next_send_section(net_device); 741c25aaf81SKY Srinivasan if (section_index != NETVSC_INVALID_INDEX) { 742c25aaf81SKY Srinivasan msg_size = netvsc_copy_to_send_buf(net_device, 743c25aaf81SKY Srinivasan section_index, 744c25aaf81SKY Srinivasan packet); 745c25aaf81SKY Srinivasan skb = (struct sk_buff *) 746c25aaf81SKY Srinivasan (unsigned long)packet->send_completion_tid; 747c25aaf81SKY Srinivasan if (skb) 748c25aaf81SKY Srinivasan dev_kfree_skb_any(skb); 749c25aaf81SKY Srinivasan packet->page_buf_cnt = 0; 750c25aaf81SKY Srinivasan } 751c25aaf81SKY Srinivasan } 752c25aaf81SKY Srinivasan packet->send_buf_index = section_index; 753c25aaf81SKY Srinivasan 754c25aaf81SKY Srinivasan 75595fa0405SHaiyang Zhang sendMessage.msg.v1_msg.send_rndis_pkt.send_buf_section_index = 756c25aaf81SKY Srinivasan section_index; 757c25aaf81SKY Srinivasan sendMessage.msg.v1_msg.send_rndis_pkt.send_buf_section_size = msg_size; 75895fa0405SHaiyang Zhang 759893f6627SHaiyang Zhang if (packet->send_completion) 76000ca8f0cSHaiyang Zhang req_id = (ulong)packet; 761f1ea3cd7SHaiyang Zhang else 762f1ea3cd7SHaiyang Zhang req_id = 0; 763f1ea3cd7SHaiyang Zhang 7645b54dac8SHaiyang Zhang out_channel = net_device->chn_table[packet->q_idx]; 7655b54dac8SHaiyang Zhang if (out_channel == NULL) 7665b54dac8SHaiyang Zhang out_channel = device->channel; 7675b54dac8SHaiyang Zhang packet->channel = out_channel; 7685b54dac8SHaiyang Zhang 76995fa0405SHaiyang Zhang if (packet->page_buf_cnt) { 7705b54dac8SHaiyang Zhang ret = vmbus_sendpacket_pagebuffer(out_channel, 77195fa0405SHaiyang Zhang packet->page_buf, 77295fa0405SHaiyang Zhang packet->page_buf_cnt, 77395fa0405SHaiyang Zhang &sendMessage, 77495fa0405SHaiyang Zhang sizeof(struct nvsp_message), 775f1ea3cd7SHaiyang Zhang req_id); 77695fa0405SHaiyang Zhang } else { 7775b54dac8SHaiyang Zhang ret = vmbus_sendpacket(out_channel, &sendMessage, 77895fa0405SHaiyang Zhang sizeof(struct nvsp_message), 779f1ea3cd7SHaiyang Zhang req_id, 78095fa0405SHaiyang Zhang VM_PKT_DATA_INBAND, 78195fa0405SHaiyang Zhang VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); 78295fa0405SHaiyang Zhang } 78395fa0405SHaiyang Zhang 7841d06825bSHaiyang Zhang if (ret == 0) { 7851d06825bSHaiyang Zhang atomic_inc(&net_device->num_outstanding_sends); 7863a67c9ccSKY Srinivasan atomic_inc(&net_device->queue_sends[q_idx]); 7875b54dac8SHaiyang Zhang 7885b54dac8SHaiyang Zhang if (hv_ringbuf_avail_percent(&out_channel->outbound) < 78933be96e4SHaiyang Zhang RING_AVAIL_PERCENT_LOWATER) { 7905b54dac8SHaiyang Zhang netif_tx_stop_queue(netdev_get_tx_queue( 7913a67c9ccSKY Srinivasan ndev, q_idx)); 7925b54dac8SHaiyang Zhang 79333be96e4SHaiyang Zhang if (atomic_read(&net_device-> 7943a67c9ccSKY Srinivasan queue_sends[q_idx]) < 1) 7955b54dac8SHaiyang Zhang netif_tx_wake_queue(netdev_get_tx_queue( 7963a67c9ccSKY Srinivasan ndev, q_idx)); 79733be96e4SHaiyang Zhang } 7981d06825bSHaiyang Zhang } else if (ret == -EAGAIN) { 7995b54dac8SHaiyang Zhang netif_tx_stop_queue(netdev_get_tx_queue( 8003a67c9ccSKY Srinivasan ndev, q_idx)); 8013a67c9ccSKY Srinivasan if (atomic_read(&net_device->queue_sends[q_idx]) < 1) { 8025b54dac8SHaiyang Zhang netif_tx_wake_queue(netdev_get_tx_queue( 8033a67c9ccSKY Srinivasan ndev, q_idx)); 80433be96e4SHaiyang Zhang ret = -ENOSPC; 80533be96e4SHaiyang Zhang } 8061d06825bSHaiyang Zhang } else { 80795fa0405SHaiyang Zhang netdev_err(ndev, "Unable to send packet %p ret %d\n", 80895fa0405SHaiyang Zhang packet, ret); 8091d06825bSHaiyang Zhang } 81095fa0405SHaiyang Zhang 81195fa0405SHaiyang Zhang return ret; 81295fa0405SHaiyang Zhang } 81395fa0405SHaiyang Zhang 81495fa0405SHaiyang Zhang static void netvsc_send_recv_completion(struct hv_device *device, 8155b54dac8SHaiyang Zhang struct vmbus_channel *channel, 81697c1723aSKY Srinivasan struct netvsc_device *net_device, 81763f6921dSHaiyang Zhang u64 transaction_id, u32 status) 81895fa0405SHaiyang Zhang { 81995fa0405SHaiyang Zhang struct nvsp_message recvcompMessage; 82095fa0405SHaiyang Zhang int retries = 0; 82195fa0405SHaiyang Zhang int ret; 82295fa0405SHaiyang Zhang struct net_device *ndev; 82395fa0405SHaiyang Zhang 82495fa0405SHaiyang Zhang ndev = net_device->ndev; 82595fa0405SHaiyang Zhang 82695fa0405SHaiyang Zhang recvcompMessage.hdr.msg_type = 82795fa0405SHaiyang Zhang NVSP_MSG1_TYPE_SEND_RNDIS_PKT_COMPLETE; 82895fa0405SHaiyang Zhang 82963f6921dSHaiyang Zhang recvcompMessage.msg.v1_msg.send_rndis_pkt_complete.status = status; 83095fa0405SHaiyang Zhang 83195fa0405SHaiyang Zhang retry_send_cmplt: 83295fa0405SHaiyang Zhang /* Send the completion */ 8335b54dac8SHaiyang Zhang ret = vmbus_sendpacket(channel, &recvcompMessage, 83495fa0405SHaiyang Zhang sizeof(struct nvsp_message), transaction_id, 83595fa0405SHaiyang Zhang VM_PKT_COMP, 0); 83695fa0405SHaiyang Zhang if (ret == 0) { 83795fa0405SHaiyang Zhang /* success */ 83895fa0405SHaiyang Zhang /* no-op */ 83995fa0405SHaiyang Zhang } else if (ret == -EAGAIN) { 84095fa0405SHaiyang Zhang /* no more room...wait a bit and attempt to retry 3 times */ 84195fa0405SHaiyang Zhang retries++; 84295fa0405SHaiyang Zhang netdev_err(ndev, "unable to send receive completion pkt" 84395fa0405SHaiyang Zhang " (tid %llx)...retrying %d\n", transaction_id, retries); 84495fa0405SHaiyang Zhang 84595fa0405SHaiyang Zhang if (retries < 4) { 84695fa0405SHaiyang Zhang udelay(100); 84795fa0405SHaiyang Zhang goto retry_send_cmplt; 84895fa0405SHaiyang Zhang } else { 84995fa0405SHaiyang Zhang netdev_err(ndev, "unable to send receive " 85095fa0405SHaiyang Zhang "completion pkt (tid %llx)...give up retrying\n", 85195fa0405SHaiyang Zhang transaction_id); 85295fa0405SHaiyang Zhang } 85395fa0405SHaiyang Zhang } else { 85495fa0405SHaiyang Zhang netdev_err(ndev, "unable to send receive " 85595fa0405SHaiyang Zhang "completion pkt - %llx\n", transaction_id); 85695fa0405SHaiyang Zhang } 85795fa0405SHaiyang Zhang } 85895fa0405SHaiyang Zhang 85997c1723aSKY Srinivasan static void netvsc_receive(struct netvsc_device *net_device, 8605b54dac8SHaiyang Zhang struct vmbus_channel *channel, 86197c1723aSKY Srinivasan struct hv_device *device, 86295fa0405SHaiyang Zhang struct vmpacket_descriptor *packet) 86395fa0405SHaiyang Zhang { 86495fa0405SHaiyang Zhang struct vmtransfer_page_packet_header *vmxferpage_packet; 86595fa0405SHaiyang Zhang struct nvsp_message *nvsp_packet; 8664baab261SHaiyang Zhang struct hv_netvsc_packet nv_pkt; 8674baab261SHaiyang Zhang struct hv_netvsc_packet *netvsc_packet = &nv_pkt; 8684baab261SHaiyang Zhang u32 status = NVSP_STAT_SUCCESS; 86945326342SHaiyang Zhang int i; 87045326342SHaiyang Zhang int count = 0; 87195fa0405SHaiyang Zhang struct net_device *ndev; 87295fa0405SHaiyang Zhang 87395fa0405SHaiyang Zhang ndev = net_device->ndev; 87495fa0405SHaiyang Zhang 87595fa0405SHaiyang Zhang /* 87695fa0405SHaiyang Zhang * All inbound packets other than send completion should be xfer page 87795fa0405SHaiyang Zhang * packet 87895fa0405SHaiyang Zhang */ 87995fa0405SHaiyang Zhang if (packet->type != VM_PKT_DATA_USING_XFER_PAGES) { 88095fa0405SHaiyang Zhang netdev_err(ndev, "Unknown packet type received - %d\n", 88195fa0405SHaiyang Zhang packet->type); 88295fa0405SHaiyang Zhang return; 88395fa0405SHaiyang Zhang } 88495fa0405SHaiyang Zhang 88595fa0405SHaiyang Zhang nvsp_packet = (struct nvsp_message *)((unsigned long)packet + 88695fa0405SHaiyang Zhang (packet->offset8 << 3)); 88795fa0405SHaiyang Zhang 88895fa0405SHaiyang Zhang /* Make sure this is a valid nvsp packet */ 88995fa0405SHaiyang Zhang if (nvsp_packet->hdr.msg_type != 89095fa0405SHaiyang Zhang NVSP_MSG1_TYPE_SEND_RNDIS_PKT) { 89195fa0405SHaiyang Zhang netdev_err(ndev, "Unknown nvsp packet type received-" 89295fa0405SHaiyang Zhang " %d\n", nvsp_packet->hdr.msg_type); 89395fa0405SHaiyang Zhang return; 89495fa0405SHaiyang Zhang } 89595fa0405SHaiyang Zhang 89695fa0405SHaiyang Zhang vmxferpage_packet = (struct vmtransfer_page_packet_header *)packet; 89795fa0405SHaiyang Zhang 89895fa0405SHaiyang Zhang if (vmxferpage_packet->xfer_pageset_id != NETVSC_RECEIVE_BUFFER_ID) { 89995fa0405SHaiyang Zhang netdev_err(ndev, "Invalid xfer page set id - " 90095fa0405SHaiyang Zhang "expecting %x got %x\n", NETVSC_RECEIVE_BUFFER_ID, 90195fa0405SHaiyang Zhang vmxferpage_packet->xfer_pageset_id); 90295fa0405SHaiyang Zhang return; 90395fa0405SHaiyang Zhang } 90495fa0405SHaiyang Zhang 9054baab261SHaiyang Zhang count = vmxferpage_packet->range_cnt; 9064baab261SHaiyang Zhang netvsc_packet->device = device; 9074baab261SHaiyang Zhang netvsc_packet->channel = channel; 90895fa0405SHaiyang Zhang 90995fa0405SHaiyang Zhang /* Each range represents 1 RNDIS pkt that contains 1 ethernet frame */ 9104baab261SHaiyang Zhang for (i = 0; i < count; i++) { 91195fa0405SHaiyang Zhang /* Initialize the netvsc packet */ 91263f6921dSHaiyang Zhang netvsc_packet->status = NVSP_STAT_SUCCESS; 91345326342SHaiyang Zhang netvsc_packet->data = (void *)((unsigned long)net_device-> 91445326342SHaiyang Zhang recv_buf + vmxferpage_packet->ranges[i].byte_offset); 91595fa0405SHaiyang Zhang netvsc_packet->total_data_buflen = 91695fa0405SHaiyang Zhang vmxferpage_packet->ranges[i].byte_count; 91795fa0405SHaiyang Zhang 91895fa0405SHaiyang Zhang /* Pass it to the upper layer */ 91995fa0405SHaiyang Zhang rndis_filter_receive(device, netvsc_packet); 92095fa0405SHaiyang Zhang 9214baab261SHaiyang Zhang if (netvsc_packet->status != NVSP_STAT_SUCCESS) 9224baab261SHaiyang Zhang status = NVSP_STAT_FAIL; 92395fa0405SHaiyang Zhang } 92495fa0405SHaiyang Zhang 9254baab261SHaiyang Zhang netvsc_send_recv_completion(device, channel, net_device, 9264baab261SHaiyang Zhang vmxferpage_packet->d.trans_id, status); 92795fa0405SHaiyang Zhang } 92895fa0405SHaiyang Zhang 9295b54dac8SHaiyang Zhang 9305b54dac8SHaiyang Zhang static void netvsc_send_table(struct hv_device *hdev, 9315b54dac8SHaiyang Zhang struct vmpacket_descriptor *vmpkt) 9325b54dac8SHaiyang Zhang { 9335b54dac8SHaiyang Zhang struct netvsc_device *nvscdev; 9345b54dac8SHaiyang Zhang struct net_device *ndev; 9355b54dac8SHaiyang Zhang struct nvsp_message *nvmsg; 9365b54dac8SHaiyang Zhang int i; 9375b54dac8SHaiyang Zhang u32 count, *tab; 9385b54dac8SHaiyang Zhang 9395b54dac8SHaiyang Zhang nvscdev = get_outbound_net_device(hdev); 9405b54dac8SHaiyang Zhang if (!nvscdev) 9415b54dac8SHaiyang Zhang return; 9425b54dac8SHaiyang Zhang ndev = nvscdev->ndev; 9435b54dac8SHaiyang Zhang 9445b54dac8SHaiyang Zhang nvmsg = (struct nvsp_message *)((unsigned long)vmpkt + 9455b54dac8SHaiyang Zhang (vmpkt->offset8 << 3)); 9465b54dac8SHaiyang Zhang 9475b54dac8SHaiyang Zhang if (nvmsg->hdr.msg_type != NVSP_MSG5_TYPE_SEND_INDIRECTION_TABLE) 9485b54dac8SHaiyang Zhang return; 9495b54dac8SHaiyang Zhang 9505b54dac8SHaiyang Zhang count = nvmsg->msg.v5_msg.send_table.count; 9515b54dac8SHaiyang Zhang if (count != VRSS_SEND_TAB_SIZE) { 9525b54dac8SHaiyang Zhang netdev_err(ndev, "Received wrong send-table size:%u\n", count); 9535b54dac8SHaiyang Zhang return; 9545b54dac8SHaiyang Zhang } 9555b54dac8SHaiyang Zhang 9565b54dac8SHaiyang Zhang tab = (u32 *)((unsigned long)&nvmsg->msg.v5_msg.send_table + 9575b54dac8SHaiyang Zhang nvmsg->msg.v5_msg.send_table.offset); 9585b54dac8SHaiyang Zhang 9595b54dac8SHaiyang Zhang for (i = 0; i < count; i++) 9605b54dac8SHaiyang Zhang nvscdev->send_table[i] = tab[i]; 9615b54dac8SHaiyang Zhang } 9625b54dac8SHaiyang Zhang 9635b54dac8SHaiyang Zhang void netvsc_channel_cb(void *context) 96495fa0405SHaiyang Zhang { 96595fa0405SHaiyang Zhang int ret; 9665b54dac8SHaiyang Zhang struct vmbus_channel *channel = (struct vmbus_channel *)context; 9675b54dac8SHaiyang Zhang struct hv_device *device; 96895fa0405SHaiyang Zhang struct netvsc_device *net_device; 96995fa0405SHaiyang Zhang u32 bytes_recvd; 97095fa0405SHaiyang Zhang u64 request_id; 97195fa0405SHaiyang Zhang struct vmpacket_descriptor *desc; 97295fa0405SHaiyang Zhang unsigned char *buffer; 97395fa0405SHaiyang Zhang int bufferlen = NETVSC_PACKET_SIZE; 97495fa0405SHaiyang Zhang struct net_device *ndev; 97595fa0405SHaiyang Zhang 9765b54dac8SHaiyang Zhang if (channel->primary_channel != NULL) 9775b54dac8SHaiyang Zhang device = channel->primary_channel->device_obj; 9785b54dac8SHaiyang Zhang else 9795b54dac8SHaiyang Zhang device = channel->device_obj; 9805b54dac8SHaiyang Zhang 98195fa0405SHaiyang Zhang net_device = get_inbound_net_device(device); 98295fa0405SHaiyang Zhang if (!net_device) 983ee0c4c39SKY Srinivasan return; 98495fa0405SHaiyang Zhang ndev = net_device->ndev; 9855b54dac8SHaiyang Zhang buffer = get_per_channel_state(channel); 98695fa0405SHaiyang Zhang 98795fa0405SHaiyang Zhang do { 9885b54dac8SHaiyang Zhang ret = vmbus_recvpacket_raw(channel, buffer, bufferlen, 98995fa0405SHaiyang Zhang &bytes_recvd, &request_id); 99095fa0405SHaiyang Zhang if (ret == 0) { 99195fa0405SHaiyang Zhang if (bytes_recvd > 0) { 99295fa0405SHaiyang Zhang desc = (struct vmpacket_descriptor *)buffer; 99395fa0405SHaiyang Zhang switch (desc->type) { 99495fa0405SHaiyang Zhang case VM_PKT_COMP: 99597c1723aSKY Srinivasan netvsc_send_completion(net_device, 99697c1723aSKY Srinivasan device, desc); 99795fa0405SHaiyang Zhang break; 99895fa0405SHaiyang Zhang 99995fa0405SHaiyang Zhang case VM_PKT_DATA_USING_XFER_PAGES: 10005b54dac8SHaiyang Zhang netvsc_receive(net_device, channel, 100197c1723aSKY Srinivasan device, desc); 100295fa0405SHaiyang Zhang break; 100395fa0405SHaiyang Zhang 10045b54dac8SHaiyang Zhang case VM_PKT_DATA_INBAND: 10055b54dac8SHaiyang Zhang netvsc_send_table(device, desc); 10065b54dac8SHaiyang Zhang break; 10075b54dac8SHaiyang Zhang 100895fa0405SHaiyang Zhang default: 100995fa0405SHaiyang Zhang netdev_err(ndev, 101095fa0405SHaiyang Zhang "unhandled packet type %d, " 101195fa0405SHaiyang Zhang "tid %llx len %d\n", 101295fa0405SHaiyang Zhang desc->type, request_id, 101395fa0405SHaiyang Zhang bytes_recvd); 101495fa0405SHaiyang Zhang break; 101595fa0405SHaiyang Zhang } 101695fa0405SHaiyang Zhang 101795fa0405SHaiyang Zhang } else { 1018ee0c4c39SKY Srinivasan /* 1019ee0c4c39SKY Srinivasan * We are done for this pass. 1020ee0c4c39SKY Srinivasan */ 102195fa0405SHaiyang Zhang break; 102295fa0405SHaiyang Zhang } 1023ee0c4c39SKY Srinivasan 102495fa0405SHaiyang Zhang } else if (ret == -ENOBUFS) { 1025ee0c4c39SKY Srinivasan if (bufferlen > NETVSC_PACKET_SIZE) 1026ee0c4c39SKY Srinivasan kfree(buffer); 102795fa0405SHaiyang Zhang /* Handle large packet */ 102895fa0405SHaiyang Zhang buffer = kmalloc(bytes_recvd, GFP_ATOMIC); 102995fa0405SHaiyang Zhang if (buffer == NULL) { 103095fa0405SHaiyang Zhang /* Try again next time around */ 103195fa0405SHaiyang Zhang netdev_err(ndev, 103295fa0405SHaiyang Zhang "unable to allocate buffer of size " 103395fa0405SHaiyang Zhang "(%d)!!\n", bytes_recvd); 103495fa0405SHaiyang Zhang break; 103595fa0405SHaiyang Zhang } 103695fa0405SHaiyang Zhang 103795fa0405SHaiyang Zhang bufferlen = bytes_recvd; 103895fa0405SHaiyang Zhang } 103995fa0405SHaiyang Zhang } while (1); 104095fa0405SHaiyang Zhang 1041ee0c4c39SKY Srinivasan if (bufferlen > NETVSC_PACKET_SIZE) 104295fa0405SHaiyang Zhang kfree(buffer); 104395fa0405SHaiyang Zhang return; 104495fa0405SHaiyang Zhang } 104595fa0405SHaiyang Zhang 104695fa0405SHaiyang Zhang /* 104795fa0405SHaiyang Zhang * netvsc_device_add - Callback when the device belonging to this 104895fa0405SHaiyang Zhang * driver is added 104995fa0405SHaiyang Zhang */ 105095fa0405SHaiyang Zhang int netvsc_device_add(struct hv_device *device, void *additional_info) 105195fa0405SHaiyang Zhang { 105295fa0405SHaiyang Zhang int ret = 0; 105395fa0405SHaiyang Zhang int ring_size = 105495fa0405SHaiyang Zhang ((struct netvsc_device_info *)additional_info)->ring_size; 105595fa0405SHaiyang Zhang struct netvsc_device *net_device; 105695fa0405SHaiyang Zhang struct net_device *ndev; 105795fa0405SHaiyang Zhang 105895fa0405SHaiyang Zhang net_device = alloc_net_device(device); 1059b1c84927SDan Carpenter if (!net_device) 1060b1c84927SDan Carpenter return -ENOMEM; 106195fa0405SHaiyang Zhang 10625b54dac8SHaiyang Zhang net_device->ring_size = ring_size; 10635b54dac8SHaiyang Zhang 106495fa0405SHaiyang Zhang /* 106595fa0405SHaiyang Zhang * Coming into this function, struct net_device * is 106695fa0405SHaiyang Zhang * registered as the driver private data. 106795fa0405SHaiyang Zhang * In alloc_net_device(), we register struct netvsc_device * 106895fa0405SHaiyang Zhang * as the driver private data and stash away struct net_device * 106995fa0405SHaiyang Zhang * in struct netvsc_device *. 107095fa0405SHaiyang Zhang */ 107195fa0405SHaiyang Zhang ndev = net_device->ndev; 107295fa0405SHaiyang Zhang 107395fa0405SHaiyang Zhang /* Initialize the NetVSC channel extension */ 107495fa0405SHaiyang Zhang init_completion(&net_device->channel_init_wait); 107595fa0405SHaiyang Zhang 10765b54dac8SHaiyang Zhang set_per_channel_state(device->channel, net_device->cb_buffer); 10775b54dac8SHaiyang Zhang 107895fa0405SHaiyang Zhang /* Open the channel */ 107995fa0405SHaiyang Zhang ret = vmbus_open(device->channel, ring_size * PAGE_SIZE, 108095fa0405SHaiyang Zhang ring_size * PAGE_SIZE, NULL, 0, 10815b54dac8SHaiyang Zhang netvsc_channel_cb, device->channel); 108295fa0405SHaiyang Zhang 108395fa0405SHaiyang Zhang if (ret != 0) { 108495fa0405SHaiyang Zhang netdev_err(ndev, "unable to open channel: %d\n", ret); 108595fa0405SHaiyang Zhang goto cleanup; 108695fa0405SHaiyang Zhang } 108795fa0405SHaiyang Zhang 108895fa0405SHaiyang Zhang /* Channel is opened */ 108995fa0405SHaiyang Zhang pr_info("hv_netvsc channel opened successfully\n"); 109095fa0405SHaiyang Zhang 10915b54dac8SHaiyang Zhang net_device->chn_table[0] = device->channel; 10925b54dac8SHaiyang Zhang 109395fa0405SHaiyang Zhang /* Connect with the NetVsp */ 109495fa0405SHaiyang Zhang ret = netvsc_connect_vsp(device); 109595fa0405SHaiyang Zhang if (ret != 0) { 109695fa0405SHaiyang Zhang netdev_err(ndev, 109795fa0405SHaiyang Zhang "unable to connect to NetVSP - %d\n", ret); 109895fa0405SHaiyang Zhang goto close; 109995fa0405SHaiyang Zhang } 110095fa0405SHaiyang Zhang 110195fa0405SHaiyang Zhang return ret; 110295fa0405SHaiyang Zhang 110395fa0405SHaiyang Zhang close: 110495fa0405SHaiyang Zhang /* Now, we can close the channel safely */ 110595fa0405SHaiyang Zhang vmbus_close(device->channel); 110695fa0405SHaiyang Zhang 110795fa0405SHaiyang Zhang cleanup: 1108f90251c8SHaiyang Zhang free_netvsc_device(net_device); 110995fa0405SHaiyang Zhang 111095fa0405SHaiyang Zhang return ret; 111195fa0405SHaiyang Zhang } 1112