netvsc.c revision 4d447c9a6ebc0142d320f075c5bac6d202a79fd4
1fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen/* 2fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen * Copyright (c) 2009, Microsoft Corporation. 3fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen * 4fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen * This program is free software; you can redistribute it and/or modify it 5fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen * under the terms and conditions of the GNU General Public License, 6fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen * version 2, as published by the Free Software Foundation. 7fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen * 8fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen * This program is distributed in the hope it will be useful, but WITHOUT 9fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen * more details. 12fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen * 13fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen * You should have received a copy of the GNU General Public License along with 14fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 15fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen * Place - Suite 330, Boston, MA 02111-1307 USA. 16fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen * 17fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen * Authors: 18d0e94d17ed8590d53252212414a627125825b379Haiyang Zhang * Haiyang Zhang <haiyangz@microsoft.com> 19fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen * Hank Janssen <hjanssen@microsoft.com> 20fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen */ 21eb335bc42781ddc19da98a3c74add1013ba08da2Hank Janssen#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 22eb335bc42781ddc19da98a3c74add1013ba08da2Hank Janssen 235654e932262840f853233317689fc59536226d76Greg Kroah-Hartman#include <linux/kernel.h> 240c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan#include <linux/sched.h> 250c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan#include <linux/wait.h> 260ffa63b09bf99ce3ee879c7de1c687267a90d20bGreg Kroah-Hartman#include <linux/mm.h> 27b4362c9c1fe8bec487e275f92fdf57c585ac236aGreg Kroah-Hartman#include <linux/delay.h> 2821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman#include <linux/io.h> 295a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 30d9871158718778ff060f08cbee0c61eb23041671Haiyang Zhang#include <linux/netdevice.h> 31f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang#include <linux/if_ether.h> 323f335ea2131b14bca2333b4316c8d4dd737e30dbK. Y. Srinivasan 335ca7252a7e2be5e05772f202d94e173b7224e7a9K. Y. Srinivasan#include "hyperv_net.h" 34fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 35fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 365a71ae303c0f82968d93d86724c1d94d753b34d7Haiyang Zhangstatic struct netvsc_device *alloc_net_device(struct hv_device *device) 37fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{ 3885799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang struct netvsc_device *net_device; 392ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan struct net_device *ndev = hv_get_drvdata(device); 40fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 4185799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang net_device = kzalloc(sizeof(struct netvsc_device), GFP_KERNEL); 4285799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang if (!net_device) 43fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen return NULL; 44fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 454d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang net_device->start_remove = false; 46c38b9c7118b95aa48bfa38d3bcd241dba3d23c10K. Y. Srinivasan net_device->destroy = false; 4753d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang net_device->dev = device; 482ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan net_device->ndev = ndev; 49fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 502ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan hv_set_drvdata(device, net_device); 5185799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang return net_device; 52fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen} 53fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 545a71ae303c0f82968d93d86724c1d94d753b34d7Haiyang Zhangstatic struct netvsc_device *get_outbound_net_device(struct hv_device *device) 55fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{ 5685799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang struct netvsc_device *net_device; 57fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 582ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan net_device = hv_get_drvdata(device); 599d88f33a1530f4241227226e7479d36ac959e9ceK. Y. Srinivasan if (net_device && net_device->destroy) 6085799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang net_device = NULL; 61fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 6285799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang return net_device; 63fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen} 64fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 655a71ae303c0f82968d93d86724c1d94d753b34d7Haiyang Zhangstatic struct netvsc_device *get_inbound_net_device(struct hv_device *device) 66fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{ 6785799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang struct netvsc_device *net_device; 68fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 692ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan net_device = hv_get_drvdata(device); 709d88f33a1530f4241227226e7479d36ac959e9ceK. Y. Srinivasan 719d88f33a1530f4241227226e7479d36ac959e9ceK. Y. Srinivasan if (!net_device) 729d88f33a1530f4241227226e7479d36ac959e9ceK. Y. Srinivasan goto get_in_err; 739d88f33a1530f4241227226e7479d36ac959e9ceK. Y. Srinivasan 749d88f33a1530f4241227226e7479d36ac959e9ceK. Y. Srinivasan if (net_device->destroy && 759d88f33a1530f4241227226e7479d36ac959e9ceK. Y. Srinivasan atomic_read(&net_device->num_outstanding_sends) == 0) 7685799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang net_device = NULL; 77fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 789d88f33a1530f4241227226e7479d36ac959e9ceK. Y. Srinivasanget_in_err: 7985799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang return net_device; 80fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen} 81fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 82fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 83ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhangstatic int netvsc_destroy_recv_buf(struct netvsc_device *net_device) 84ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang{ 85ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang struct nvsp_message *revoke_packet; 86ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang int ret = 0; 872ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan struct net_device *ndev = net_device->ndev; 88ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang 89ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang /* 90ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang * If we got a section count, it means we received a 91ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang * SendReceiveBufferComplete msg (ie sent 92ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang * NvspMessage1TypeSendReceiveBuffer msg) therefore, we need 93ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang * to send a revoke msg here 94ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang */ 95ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang if (net_device->recv_section_cnt) { 96ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang /* Send the revoke receive buffer */ 97ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang revoke_packet = &net_device->revoke_packet; 98ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang memset(revoke_packet, 0, sizeof(struct nvsp_message)); 99ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang 100ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang revoke_packet->hdr.msg_type = 101ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang NVSP_MSG1_TYPE_REVOKE_RECV_BUF; 102ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang revoke_packet->msg.v1_msg. 103ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang revoke_recv_buf.id = NETVSC_RECEIVE_BUFFER_ID; 104ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang 105ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang ret = vmbus_sendpacket(net_device->dev->channel, 106ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang revoke_packet, 107ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang sizeof(struct nvsp_message), 108ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang (unsigned long)revoke_packet, 109ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang VM_PKT_DATA_INBAND, 0); 110ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang /* 111ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang * If we failed here, we might as well return and 112ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang * have a leak rather than continue and a bugchk 113ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang */ 114ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang if (ret != 0) { 115d9871158718778ff060f08cbee0c61eb23041671Haiyang Zhang netdev_err(ndev, "unable to send " 116c909ebbd0dcf19c617408c2cfde56c4bbd4f6cb4Haiyang Zhang "revoke receive buffer to netvsp\n"); 117a3e00530469baa39ccc08b1731a4e120bd63012fK. Y. Srinivasan return ret; 118ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang } 119ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang } 120ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang 121ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang /* Teardown the gpadl on the vsp end */ 122ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang if (net_device->recv_buf_gpadl_handle) { 123ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang ret = vmbus_teardown_gpadl(net_device->dev->channel, 124ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang net_device->recv_buf_gpadl_handle); 125ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang 126ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang /* If we failed here, we might as well return and have a leak 127ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang * rather than continue and a bugchk 128ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang */ 129ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang if (ret != 0) { 130d9871158718778ff060f08cbee0c61eb23041671Haiyang Zhang netdev_err(ndev, 131c909ebbd0dcf19c617408c2cfde56c4bbd4f6cb4Haiyang Zhang "unable to teardown receive buffer's gpadl\n"); 1327f9615e6f6c703c68f84460fe22b858be6c258d1Dan Carpenter return ret; 133ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang } 134ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang net_device->recv_buf_gpadl_handle = 0; 135ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang } 136ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang 137ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang if (net_device->recv_buf) { 138ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang /* Free up the receive buffer */ 139ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang free_pages((unsigned long)net_device->recv_buf, 140ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang get_order(net_device->recv_buf_size)); 141ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang net_device->recv_buf = NULL; 142ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang } 143ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang 144ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang if (net_device->recv_section) { 145ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang net_device->recv_section_cnt = 0; 146ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang kfree(net_device->recv_section); 147ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang net_device->recv_section = NULL; 148ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang } 149ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang 150ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang return ret; 151ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang} 152ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang 1535a71ae303c0f82968d93d86724c1d94d753b34d7Haiyang Zhangstatic int netvsc_init_recv_buf(struct hv_device *device) 154fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{ 15521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman int ret = 0; 15635abb21ace3413de6ea8d5c7750cedfd46111f0cK. Y. Srinivasan int t; 15785799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang struct netvsc_device *net_device; 15885799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang struct nvsp_message *init_packet; 1592ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan struct net_device *ndev; 160fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 1615a71ae303c0f82968d93d86724c1d94d753b34d7Haiyang Zhang net_device = get_outbound_net_device(device); 1622ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan if (!net_device) 163927bc33c0a239b706635b23c5cc1f3df2a3c8b86K. Y. Srinivasan return -ENODEV; 1642ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan ndev = net_device->ndev; 165fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 16653d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang net_device->recv_buf = 167df3493e0b3ba72f9b6192a91b24197cac41ce557K. Y. Srinivasan (void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO, 168df3493e0b3ba72f9b6192a91b24197cac41ce557K. Y. Srinivasan get_order(net_device->recv_buf_size)); 16953d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang if (!net_device->recv_buf) { 170d9871158718778ff060f08cbee0c61eb23041671Haiyang Zhang netdev_err(ndev, "unable to allocate receive " 171c909ebbd0dcf19c617408c2cfde56c4bbd4f6cb4Haiyang Zhang "buffer of size %d\n", net_device->recv_buf_size); 172927bc33c0a239b706635b23c5cc1f3df2a3c8b86K. Y. Srinivasan ret = -ENOMEM; 1730c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan goto cleanup; 174fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 175fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 176454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* 177454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * Establish the gpadl handle for this buffer on this 178454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * channel. Note: This call uses the vmbus connection rather 179454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * than the channel to establish the gpadl handle. 180454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton */ 18153d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang ret = vmbus_establish_gpadl(device->channel, net_device->recv_buf, 18253d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang net_device->recv_buf_size, 18353d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang &net_device->recv_buf_gpadl_handle); 18421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (ret != 0) { 185d9871158718778ff060f08cbee0c61eb23041671Haiyang Zhang netdev_err(ndev, 186c909ebbd0dcf19c617408c2cfde56c4bbd4f6cb4Haiyang Zhang "unable to establish receive buffer's gpadl\n"); 1870c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan goto cleanup; 188fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 189fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 190fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 191454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Notify the NetVsp of the gpadl handle */ 19253d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang init_packet = &net_device->channel_init_pkt; 193fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 19485799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang memset(init_packet, 0, sizeof(struct nvsp_message)); 195fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 19653d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang init_packet->hdr.msg_type = NVSP_MSG1_TYPE_SEND_RECV_BUF; 19753d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang init_packet->msg.v1_msg.send_recv_buf. 19853d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang gpadl_handle = net_device->recv_buf_gpadl_handle; 19953d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang init_packet->msg.v1_msg. 20053d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang send_recv_buf.id = NETVSC_RECEIVE_BUFFER_ID; 201fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 202454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Send the gpadl notification request */ 20385799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang ret = vmbus_sendpacket(device->channel, init_packet, 2045a4df29058625ce59f549730817961b293f58d49Greg Kroah-Hartman sizeof(struct nvsp_message), 20585799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang (unsigned long)init_packet, 206415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang VM_PKT_DATA_INBAND, 2075a4df29058625ce59f549730817961b293f58d49Greg Kroah-Hartman VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); 20821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (ret != 0) { 209d9871158718778ff060f08cbee0c61eb23041671Haiyang Zhang netdev_err(ndev, 210c909ebbd0dcf19c617408c2cfde56c4bbd4f6cb4Haiyang Zhang "unable to send receive buffer's gpadl to netvsp\n"); 2110c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan goto cleanup; 212fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 213fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 2145c5781b3f88567211ecaaada13431af15c8c6003K. Y. Srinivasan t = wait_for_completion_timeout(&net_device->channel_init_wait, 5*HZ); 21535abb21ace3413de6ea8d5c7750cedfd46111f0cK. Y. Srinivasan BUG_ON(t == 0); 2160c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan 217fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 218454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Check the response */ 21953d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang if (init_packet->msg.v1_msg. 22053d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang send_recv_buf_complete.status != NVSP_STAT_SUCCESS) { 221d9871158718778ff060f08cbee0c61eb23041671Haiyang Zhang netdev_err(ndev, "Unable to complete receive buffer " 2228bff33ab417f246dac4ab9835be6894eaddfb546Haiyang Zhang "initialization with NetVsp - status %d\n", 22353d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang init_packet->msg.v1_msg. 22453d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang send_recv_buf_complete.status); 225927bc33c0a239b706635b23c5cc1f3df2a3c8b86K. Y. Srinivasan ret = -EINVAL; 2260c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan goto cleanup; 227fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 228fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 229454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Parse the response */ 230fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 23153d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang net_device->recv_section_cnt = init_packet->msg. 23253d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang v1_msg.send_recv_buf_complete.num_sections; 233fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 234c18132005e711c07523d8c6602e5b2266ab9a0f2Haiyang Zhang net_device->recv_section = kmemdup( 235c18132005e711c07523d8c6602e5b2266ab9a0f2Haiyang Zhang init_packet->msg.v1_msg.send_recv_buf_complete.sections, 236c18132005e711c07523d8c6602e5b2266ab9a0f2Haiyang Zhang net_device->recv_section_cnt * 237c18132005e711c07523d8c6602e5b2266ab9a0f2Haiyang Zhang sizeof(struct nvsp_1_receive_buffer_section), 238c18132005e711c07523d8c6602e5b2266ab9a0f2Haiyang Zhang GFP_KERNEL); 23953d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang if (net_device->recv_section == NULL) { 240927bc33c0a239b706635b23c5cc1f3df2a3c8b86K. Y. Srinivasan ret = -EINVAL; 2410c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan goto cleanup; 242fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 243fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 24421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman /* 24521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman * For 1st release, there should only be 1 section that represents the 24621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman * entire receive buffer 24721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman */ 24853d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang if (net_device->recv_section_cnt != 1 || 24953d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang net_device->recv_section->offset != 0) { 250927bc33c0a239b706635b23c5cc1f3df2a3c8b86K. Y. Srinivasan ret = -EINVAL; 2510c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan goto cleanup; 252fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 253fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 2540c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan goto exit; 255fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 2560c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasancleanup: 2575a71ae303c0f82968d93d86724c1d94d753b34d7Haiyang Zhang netvsc_destroy_recv_buf(net_device); 258fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 2590c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasanexit: 260fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen return ret; 261fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen} 262fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 263fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 264f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang/* Negotiate NVSP protocol version */ 265f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhangstatic int negotiate_nvsp_ver(struct hv_device *device, 266f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang struct netvsc_device *net_device, 267f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang struct nvsp_message *init_packet, 268f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang u32 nvsp_ver) 269fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{ 27035abb21ace3413de6ea8d5c7750cedfd46111f0cK. Y. Srinivasan int ret, t; 271fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 27285799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang memset(init_packet, 0, sizeof(struct nvsp_message)); 27353d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang init_packet->hdr.msg_type = NVSP_MSG_TYPE_INIT; 274f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang init_packet->msg.init_msg.init.min_protocol_ver = nvsp_ver; 275f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang init_packet->msg.init_msg.init.max_protocol_ver = nvsp_ver; 276fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 277454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Send the init request */ 27885799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang ret = vmbus_sendpacket(device->channel, init_packet, 2795a4df29058625ce59f549730817961b293f58d49Greg Kroah-Hartman sizeof(struct nvsp_message), 28085799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang (unsigned long)init_packet, 281415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang VM_PKT_DATA_INBAND, 2825a4df29058625ce59f549730817961b293f58d49Greg Kroah-Hartman VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); 28321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman 284b8a3d52b2f7db637edcb62f9a332e1b35eefad13Hank Janssen if (ret != 0) 285f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang return ret; 286fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 2875c5781b3f88567211ecaaada13431af15c8c6003K. Y. Srinivasan t = wait_for_completion_timeout(&net_device->channel_init_wait, 5*HZ); 28835abb21ace3413de6ea8d5c7750cedfd46111f0cK. Y. Srinivasan 289f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang if (t == 0) 290f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang return -ETIMEDOUT; 291fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 29253d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang if (init_packet->msg.init_msg.init_complete.status != 293f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang NVSP_STAT_SUCCESS) 294f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang return -EINVAL; 295fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 296f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang if (nvsp_ver != NVSP_PROTOCOL_VERSION_2) 297f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang return 0; 298f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang 299f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang /* NVSPv2 only: Send NDIS config */ 300f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang memset(init_packet, 0, sizeof(struct nvsp_message)); 301f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang init_packet->hdr.msg_type = NVSP_MSG2_TYPE_SEND_NDIS_CONFIG; 3024d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang init_packet->msg.v2_msg.send_ndis_config.mtu = net_device->ndev->mtu; 303f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang 304f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang ret = vmbus_sendpacket(device->channel, init_packet, 305f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang sizeof(struct nvsp_message), 306f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang (unsigned long)init_packet, 307f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang VM_PKT_DATA_INBAND, 0); 308f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang 309f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang return ret; 310f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang} 311f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang 312f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhangstatic int netvsc_connect_vsp(struct hv_device *device) 313f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang{ 314f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang int ret; 315f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang struct netvsc_device *net_device; 316f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang struct nvsp_message *init_packet; 317f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang int ndis_version; 318f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang struct net_device *ndev; 319f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang 320f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang net_device = get_outbound_net_device(device); 321f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang if (!net_device) 322f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang return -ENODEV; 323f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang ndev = net_device->ndev; 324f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang 325f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang init_packet = &net_device->channel_init_pkt; 326f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang 327f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang /* Negotiate the latest NVSP protocol supported */ 328f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang if (negotiate_nvsp_ver(device, net_device, init_packet, 329f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang NVSP_PROTOCOL_VERSION_2) == 0) { 330f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang net_device->nvsp_version = NVSP_PROTOCOL_VERSION_2; 331f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang } else if (negotiate_nvsp_ver(device, net_device, init_packet, 332f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang NVSP_PROTOCOL_VERSION_1) == 0) { 333f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang net_device->nvsp_version = NVSP_PROTOCOL_VERSION_1; 334f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang } else { 3350f48c72ca63a6e1da7f226163c36fecd7a923fedK. Y. Srinivasan ret = -EPROTO; 3360c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan goto cleanup; 337fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 338f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang 339f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang pr_debug("Negotiated NVSP version:%x\n", net_device->nvsp_version); 340f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang 341454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Send the ndis version */ 34285799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang memset(init_packet, 0, sizeof(struct nvsp_message)); 343fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 34485799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang ndis_version = 0x00050000; 345fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 34653d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang init_packet->hdr.msg_type = NVSP_MSG1_TYPE_SEND_NDIS_VER; 34753d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang init_packet->msg.v1_msg. 34853d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang send_ndis_ver.ndis_major_ver = 34985799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang (ndis_version & 0xFFFF0000) >> 16; 35053d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang init_packet->msg.v1_msg. 35153d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang send_ndis_ver.ndis_minor_ver = 35285799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang ndis_version & 0xFFFF; 353fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 354454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Send the init request */ 35585799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang ret = vmbus_sendpacket(device->channel, init_packet, 3560c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan sizeof(struct nvsp_message), 3570c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan (unsigned long)init_packet, 3580c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan VM_PKT_DATA_INBAND, 0); 3590f48c72ca63a6e1da7f226163c36fecd7a923fedK. Y. Srinivasan if (ret != 0) 3600c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan goto cleanup; 361454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton 362454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Post the big receive buffer to NetVSP */ 3635a71ae303c0f82968d93d86724c1d94d753b34d7Haiyang Zhang ret = netvsc_init_recv_buf(device); 364fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 3650c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasancleanup: 366fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen return ret; 367fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen} 368fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 369648dc59899073d4d23ba346c0281dc96792725b3Haiyang Zhangstatic void netvsc_disconnect_vsp(struct netvsc_device *net_device) 370fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{ 3715a71ae303c0f82968d93d86724c1d94d753b34d7Haiyang Zhang netvsc_destroy_recv_buf(net_device); 372fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen} 373fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 3743e18951955797872558dad615851a4ca63b2770eHank Janssen/* 3755a71ae303c0f82968d93d86724c1d94d753b34d7Haiyang Zhang * netvsc_device_remove - Callback when the root bus device is removed 37621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman */ 377905620d16f5c9e7c8ff850e15f47f5700824f6fbK. Y. Srinivasanint netvsc_device_remove(struct hv_device *device) 378fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{ 37985799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang struct netvsc_device *net_device; 38085799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang struct hv_netvsc_packet *netvsc_packet, *pos; 381c38b9c7118b95aa48bfa38d3bcd241dba3d23c10K. Y. Srinivasan unsigned long flags; 382fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 3832ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan net_device = hv_get_drvdata(device); 384c38b9c7118b95aa48bfa38d3bcd241dba3d23c10K. Y. Srinivasan spin_lock_irqsave(&device->channel->inbound_lock, flags); 385c38b9c7118b95aa48bfa38d3bcd241dba3d23c10K. Y. Srinivasan net_device->destroy = true; 386c38b9c7118b95aa48bfa38d3bcd241dba3d23c10K. Y. Srinivasan spin_unlock_irqrestore(&device->channel->inbound_lock, flags); 387c38b9c7118b95aa48bfa38d3bcd241dba3d23c10K. Y. Srinivasan 388454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Wait for all send completions */ 38953d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang while (atomic_read(&net_device->num_outstanding_sends)) { 390d9871158718778ff060f08cbee0c61eb23041671Haiyang Zhang dev_info(&device->device, 391c909ebbd0dcf19c617408c2cfde56c4bbd4f6cb4Haiyang Zhang "waiting for %d requests to complete...\n", 392eb335bc42781ddc19da98a3c74add1013ba08da2Hank Janssen atomic_read(&net_device->num_outstanding_sends)); 393b4362c9c1fe8bec487e275f92fdf57c585ac236aGreg Kroah-Hartman udelay(100); 394fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 395fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 396648dc59899073d4d23ba346c0281dc96792725b3Haiyang Zhang netvsc_disconnect_vsp(net_device); 397fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 3983852409b88e8ec2a8abb28db5be25a7503297208K. Y. Srinivasan /* 3999d88f33a1530f4241227226e7479d36ac959e9ceK. Y. Srinivasan * Since we have already drained, we don't need to busy wait 4009d88f33a1530f4241227226e7479d36ac959e9ceK. Y. Srinivasan * as was done in final_release_stor_device() 4019d88f33a1530f4241227226e7479d36ac959e9ceK. Y. Srinivasan * Note that we cannot set the ext pointer to NULL until 4029d88f33a1530f4241227226e7479d36ac959e9ceK. Y. Srinivasan * we have drained - to drain the outgoing packets, we need to 4039d88f33a1530f4241227226e7479d36ac959e9ceK. Y. Srinivasan * allow incoming packets. 4043852409b88e8ec2a8abb28db5be25a7503297208K. Y. Srinivasan */ 4059d88f33a1530f4241227226e7479d36ac959e9ceK. Y. Srinivasan 4069d88f33a1530f4241227226e7479d36ac959e9ceK. Y. Srinivasan spin_lock_irqsave(&device->channel->inbound_lock, flags); 4072ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan hv_set_drvdata(device, NULL); 4089d88f33a1530f4241227226e7479d36ac959e9ceK. Y. Srinivasan spin_unlock_irqrestore(&device->channel->inbound_lock, flags); 4093852409b88e8ec2a8abb28db5be25a7503297208K. Y. Srinivasan 41086c921af41f0d40ff9105a73fb20378440f0299fK. Y. Srinivasan /* 41186c921af41f0d40ff9105a73fb20378440f0299fK. Y. Srinivasan * At this point, no one should be accessing net_device 41286c921af41f0d40ff9105a73fb20378440f0299fK. Y. Srinivasan * except in here 41386c921af41f0d40ff9105a73fb20378440f0299fK. Y. Srinivasan */ 414c909ebbd0dcf19c617408c2cfde56c4bbd4f6cb4Haiyang Zhang dev_notice(&device->device, "net device safe to remove\n"); 415fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 416454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Now, we can close the channel safely */ 41785799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang vmbus_close(device->channel); 418fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 419454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Release all resources */ 42085799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang list_for_each_entry_safe(netvsc_packet, pos, 42153d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang &net_device->recv_pkt_list, list_ent) { 42272a2f5bd53bf83302f4dcfe8500d4ec440545d27Haiyang Zhang list_del(&netvsc_packet->list_ent); 42385799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang kfree(netvsc_packet); 424fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 425fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 426356c4657193c8a5b3aff84fe8cdf5ddc64742801K. Y. Srinivasan kfree(net_device); 42721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman return 0; 428fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen} 429fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 4305a71ae303c0f82968d93d86724c1d94d753b34d7Haiyang Zhangstatic void netvsc_send_completion(struct hv_device *device, 43185799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang struct vmpacket_descriptor *packet) 432fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{ 43385799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang struct netvsc_device *net_device; 43485799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang struct nvsp_message *nvsp_packet; 43585799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang struct hv_netvsc_packet *nvsc_packet; 4362ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan struct net_device *ndev; 437fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 4385a71ae303c0f82968d93d86724c1d94d753b34d7Haiyang Zhang net_device = get_inbound_net_device(device); 4392ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan if (!net_device) 440fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen return; 4412ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan ndev = net_device->ndev; 442fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 44385799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang nvsp_packet = (struct nvsp_message *)((unsigned long)packet + 444415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang (packet->offset8 << 3)); 445fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 44653d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang if ((nvsp_packet->hdr.msg_type == NVSP_MSG_TYPE_INIT_COMPLETE) || 44753d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang (nvsp_packet->hdr.msg_type == 44853d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang NVSP_MSG1_TYPE_SEND_RECV_BUF_COMPLETE) || 44953d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang (nvsp_packet->hdr.msg_type == 45053d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang NVSP_MSG1_TYPE_SEND_SEND_BUF_COMPLETE)) { 451454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Copy the response back */ 45253d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang memcpy(&net_device->channel_init_pkt, nvsp_packet, 45321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman sizeof(struct nvsp_message)); 45435abb21ace3413de6ea8d5c7750cedfd46111f0cK. Y. Srinivasan complete(&net_device->channel_init_wait); 45553d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang } else if (nvsp_packet->hdr.msg_type == 45653d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang NVSP_MSG1_TYPE_SEND_RNDIS_PKT_COMPLETE) { 457454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Get the send context */ 45885799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang nvsc_packet = (struct hv_netvsc_packet *)(unsigned long) 459415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang packet->trans_id; 460fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 461454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Notify the layer above us */ 46272a2f5bd53bf83302f4dcfe8500d4ec440545d27Haiyang Zhang nvsc_packet->completion.send.send_completion( 46372a2f5bd53bf83302f4dcfe8500d4ec440545d27Haiyang Zhang nvsc_packet->completion.send.send_completion_ctx); 464fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 46553d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang atomic_dec(&net_device->num_outstanding_sends); 4661d06825b0ede541f63b5577435abd2fc649a9b5eHaiyang Zhang 4674d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang if (netif_queue_stopped(ndev) && !net_device->start_remove) 4681d06825b0ede541f63b5577435abd2fc649a9b5eHaiyang Zhang netif_wake_queue(ndev); 46921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman } else { 470d9871158718778ff060f08cbee0c61eb23041671Haiyang Zhang netdev_err(ndev, "Unknown send completion packet type- " 471c909ebbd0dcf19c617408c2cfde56c4bbd4f6cb4Haiyang Zhang "%d received!!\n", nvsp_packet->hdr.msg_type); 472fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 473fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 474fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen} 475fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 476f9819f05f2c5a3fb61853c5fc8d20d61dfbfe89bK. Y. Srinivasanint netvsc_send(struct hv_device *device, 47785799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang struct hv_netvsc_packet *packet) 478fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{ 47985799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang struct netvsc_device *net_device; 48021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman int ret = 0; 481223c1aa632dbad672ad9b907e5d5e8f385417945Greg Kroah-Hartman struct nvsp_message sendMessage; 4822ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan struct net_device *ndev; 483fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 4845a71ae303c0f82968d93d86724c1d94d753b34d7Haiyang Zhang net_device = get_outbound_net_device(device); 4852ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan if (!net_device) 486ff2bd69ae3ec164b606114fcbd9b9e4d5f2bcdc7K. Y. Srinivasan return -ENODEV; 4872ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan ndev = net_device->ndev; 488fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 48953d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang sendMessage.hdr.msg_type = NVSP_MSG1_TYPE_SEND_RNDIS_PKT; 49072a2f5bd53bf83302f4dcfe8500d4ec440545d27Haiyang Zhang if (packet->is_data_pkt) { 49121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman /* 0 is RMC_DATA; */ 49253d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang sendMessage.msg.v1_msg.send_rndis_pkt.channel_type = 0; 49321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman } else { 49421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman /* 1 is RMC_CONTROL; */ 49553d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang sendMessage.msg.v1_msg.send_rndis_pkt.channel_type = 1; 49621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman } 497fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 498454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Not using send buffer section */ 49953d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang sendMessage.msg.v1_msg.send_rndis_pkt.send_buf_section_index = 50053d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang 0xFFFFFFFF; 50153d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang sendMessage.msg.v1_msg.send_rndis_pkt.send_buf_section_size = 0; 50221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman 50372a2f5bd53bf83302f4dcfe8500d4ec440545d27Haiyang Zhang if (packet->page_buf_cnt) { 50485799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang ret = vmbus_sendpacket_pagebuffer(device->channel, 50572a2f5bd53bf83302f4dcfe8500d4ec440545d27Haiyang Zhang packet->page_buf, 50672a2f5bd53bf83302f4dcfe8500d4ec440545d27Haiyang Zhang packet->page_buf_cnt, 507ff3f8eece20bb45f8b515641b3797b6047a657fdGreg Kroah-Hartman &sendMessage, 508ff3f8eece20bb45f8b515641b3797b6047a657fdGreg Kroah-Hartman sizeof(struct nvsp_message), 50985799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang (unsigned long)packet); 51021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman } else { 51185799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang ret = vmbus_sendpacket(device->channel, &sendMessage, 512e4d59ac5c6bbb671b61108dad0c7cd33c753ce22Haiyang Zhang sizeof(struct nvsp_message), 513e4d59ac5c6bbb671b61108dad0c7cd33c753ce22Haiyang Zhang (unsigned long)packet, 514e4d59ac5c6bbb671b61108dad0c7cd33c753ce22Haiyang Zhang VM_PKT_DATA_INBAND, 515e4d59ac5c6bbb671b61108dad0c7cd33c753ce22Haiyang Zhang VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); 516fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 517fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 518fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 5191d06825b0ede541f63b5577435abd2fc649a9b5eHaiyang Zhang if (ret == 0) { 5201d06825b0ede541f63b5577435abd2fc649a9b5eHaiyang Zhang atomic_inc(&net_device->num_outstanding_sends); 5211d06825b0ede541f63b5577435abd2fc649a9b5eHaiyang Zhang } else if (ret == -EAGAIN) { 5221d06825b0ede541f63b5577435abd2fc649a9b5eHaiyang Zhang netif_stop_queue(ndev); 5231d06825b0ede541f63b5577435abd2fc649a9b5eHaiyang Zhang if (atomic_read(&net_device->num_outstanding_sends) < 1) 5241d06825b0ede541f63b5577435abd2fc649a9b5eHaiyang Zhang netif_wake_queue(ndev); 5251d06825b0ede541f63b5577435abd2fc649a9b5eHaiyang Zhang } else { 526d9871158718778ff060f08cbee0c61eb23041671Haiyang Zhang netdev_err(ndev, "Unable to send packet %p ret %d\n", 52785799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang packet, ret); 5281d06825b0ede541f63b5577435abd2fc649a9b5eHaiyang Zhang } 529fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 530fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen return ret; 531fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen} 532fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 5335fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhangstatic void netvsc_send_recv_completion(struct hv_device *device, 5345fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang u64 transaction_id) 5355fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang{ 5365fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang struct nvsp_message recvcompMessage; 5375fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang int retries = 0; 5385fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang int ret; 5392ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan struct net_device *ndev; 5402ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan struct netvsc_device *net_device = hv_get_drvdata(device); 5412ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan 5422ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan ndev = net_device->ndev; 5435fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang 5445fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang recvcompMessage.hdr.msg_type = 5455fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang NVSP_MSG1_TYPE_SEND_RNDIS_PKT_COMPLETE; 5465fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang 5475fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang /* FIXME: Pass in the status */ 5485fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang recvcompMessage.msg.v1_msg.send_rndis_pkt_complete.status = 5495fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang NVSP_STAT_SUCCESS; 5505fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang 5515fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhangretry_send_cmplt: 5525fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang /* Send the completion */ 5535fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang ret = vmbus_sendpacket(device->channel, &recvcompMessage, 5545fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang sizeof(struct nvsp_message), transaction_id, 5555fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang VM_PKT_COMP, 0); 5565fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang if (ret == 0) { 5575fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang /* success */ 5585fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang /* no-op */ 559d2598f017f02bbc3623503c6e08f22f7ea473cddK. Y. Srinivasan } else if (ret == -EAGAIN) { 5605fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang /* no more room...wait a bit and attempt to retry 3 times */ 5615fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang retries++; 562d9871158718778ff060f08cbee0c61eb23041671Haiyang Zhang netdev_err(ndev, "unable to send receive completion pkt" 563c909ebbd0dcf19c617408c2cfde56c4bbd4f6cb4Haiyang Zhang " (tid %llx)...retrying %d\n", transaction_id, retries); 5645fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang 5655fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang if (retries < 4) { 5665fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang udelay(100); 5675fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang goto retry_send_cmplt; 5685fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang } else { 569d9871158718778ff060f08cbee0c61eb23041671Haiyang Zhang netdev_err(ndev, "unable to send receive " 570c909ebbd0dcf19c617408c2cfde56c4bbd4f6cb4Haiyang Zhang "completion pkt (tid %llx)...give up retrying\n", 5715fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang transaction_id); 5725fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang } 5735fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang } else { 574d9871158718778ff060f08cbee0c61eb23041671Haiyang Zhang netdev_err(ndev, "unable to send receive " 575c909ebbd0dcf19c617408c2cfde56c4bbd4f6cb4Haiyang Zhang "completion pkt - %llx\n", transaction_id); 5765fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang } 5775fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang} 5785fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang 57957991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang/* Send a receive completion packet to RNDIS device (ie NetVsp) */ 58057991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhangstatic void netvsc_receive_completion(void *context) 58157991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang{ 58257991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang struct hv_netvsc_packet *packet = context; 58357991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang struct hv_device *device = (struct hv_device *)packet->device; 58457991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang struct netvsc_device *net_device; 58557991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang u64 transaction_id = 0; 58657991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang bool fsend_receive_comp = false; 58757991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang unsigned long flags; 5882ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan struct net_device *ndev; 58957991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang 59057991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang /* 59157991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang * Even though it seems logical to do a GetOutboundNetDevice() here to 59257991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang * send out receive completion, we are using GetInboundNetDevice() 59357991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang * since we may have disable outbound traffic already. 59457991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang */ 59557991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang net_device = get_inbound_net_device(device); 5962ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan if (!net_device) 59757991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang return; 5982ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan ndev = net_device->ndev; 59957991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang 60057991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang /* Overloading use of the lock. */ 60157991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang spin_lock_irqsave(&net_device->recv_pkt_list_lock, flags); 60257991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang 60357991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang packet->xfer_page_pkt->count--; 60457991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang 60557991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang /* 60657991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang * Last one in the line that represent 1 xfer page packet. 60757991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang * Return the xfer page packet itself to the freelist 60857991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang */ 60957991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang if (packet->xfer_page_pkt->count == 0) { 61057991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang fsend_receive_comp = true; 61157991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang transaction_id = packet->completion.recv.recv_completion_tid; 61257991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang list_add_tail(&packet->xfer_page_pkt->list_ent, 61357991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang &net_device->recv_pkt_list); 61457991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang 61557991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang } 61657991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang 61757991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang /* Put the packet back */ 61857991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang list_add_tail(&packet->list_ent, &net_device->recv_pkt_list); 61957991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang spin_unlock_irqrestore(&net_device->recv_pkt_list_lock, flags); 62057991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang 62157991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang /* Send a receive completion for the xfer page packet */ 62257991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang if (fsend_receive_comp) 62357991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang netvsc_send_recv_completion(device, transaction_id); 62457991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang 62557991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang} 62657991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang 6275a71ae303c0f82968d93d86724c1d94d753b34d7Haiyang Zhangstatic void netvsc_receive(struct hv_device *device, 62885799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang struct vmpacket_descriptor *packet) 629fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{ 63085799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang struct netvsc_device *net_device; 63185799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang struct vmtransfer_page_packet_header *vmxferpage_packet; 63285799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang struct nvsp_message *nvsp_packet; 63385799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang struct hv_netvsc_packet *netvsc_packet = NULL; 6347e23a6e9626bf93242712f146a9657d38dda497bGreg Kroah-Hartman /* struct netvsc_driver *netvscDriver; */ 63585799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang struct xferpage_packet *xferpage_packet = NULL; 636453263421f88b4a7e508c2e7b639c97e99c5b118Haiyang Zhang int i; 637453263421f88b4a7e508c2e7b639c97e99c5b118Haiyang Zhang int count = 0; 6386436873afce6f20fecc0c5099db899b25e1e6c2bGreg Kroah-Hartman unsigned long flags; 6392ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan struct net_device *ndev; 640779b4d17c177de592141ab01d2a66d025ff4d238K. Y. Srinivasan 641d29274efb73735c6a94f20214b1e4ea994da8848Bill Pemberton LIST_HEAD(listHead); 642fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 6435a71ae303c0f82968d93d86724c1d94d753b34d7Haiyang Zhang net_device = get_inbound_net_device(device); 6442ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan if (!net_device) 645fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen return; 6462ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan ndev = net_device->ndev; 647fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 64821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman /* 64921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman * All inbound packets other than send completion should be xfer page 65021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman * packet 65121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman */ 652415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang if (packet->type != VM_PKT_DATA_USING_XFER_PAGES) { 653d9871158718778ff060f08cbee0c61eb23041671Haiyang Zhang netdev_err(ndev, "Unknown packet type received - %d\n", 654415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang packet->type); 655fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen return; 656fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 657fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 65885799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang nvsp_packet = (struct nvsp_message *)((unsigned long)packet + 659415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang (packet->offset8 << 3)); 660fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 661454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Make sure this is a valid nvsp packet */ 66253d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang if (nvsp_packet->hdr.msg_type != 66353d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang NVSP_MSG1_TYPE_SEND_RNDIS_PKT) { 664d9871158718778ff060f08cbee0c61eb23041671Haiyang Zhang netdev_err(ndev, "Unknown nvsp packet type received-" 665c909ebbd0dcf19c617408c2cfde56c4bbd4f6cb4Haiyang Zhang " %d\n", nvsp_packet->hdr.msg_type); 666fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen return; 667fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 668fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 66985799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang vmxferpage_packet = (struct vmtransfer_page_packet_header *)packet; 670fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 671415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang if (vmxferpage_packet->xfer_pageset_id != NETVSC_RECEIVE_BUFFER_ID) { 672d9871158718778ff060f08cbee0c61eb23041671Haiyang Zhang netdev_err(ndev, "Invalid xfer page set id - " 673c909ebbd0dcf19c617408c2cfde56c4bbd4f6cb4Haiyang Zhang "expecting %x got %x\n", NETVSC_RECEIVE_BUFFER_ID, 674415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang vmxferpage_packet->xfer_pageset_id); 675fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen return; 676fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 677fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 678454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* 679454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * Grab free packets (range count + 1) to represent this xfer 680454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * page packet. +1 to represent the xfer page packet itself. 681454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * We grab it here so that we know exactly how many we can 682454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * fulfil 683454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton */ 68453d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang spin_lock_irqsave(&net_device->recv_pkt_list_lock, flags); 68553d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang while (!list_empty(&net_device->recv_pkt_list)) { 68653d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang list_move_tail(net_device->recv_pkt_list.next, &listHead); 687415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang if (++count == vmxferpage_packet->range_cnt + 1) 688fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen break; 689fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 69053d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang spin_unlock_irqrestore(&net_device->recv_pkt_list_lock, flags); 691fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 692454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* 693454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * We need at least 2 netvsc pkts (1 to represent the xfer 694454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * page and at least 1 for the range) i.e. we can handled 695454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * some of the xfer page packet ranges... 696454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton */ 69721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (count < 2) { 698d9871158718778ff060f08cbee0c61eb23041671Haiyang Zhang netdev_err(ndev, "Got only %d netvsc pkt...needed " 699c909ebbd0dcf19c617408c2cfde56c4bbd4f6cb4Haiyang Zhang "%d pkts. Dropping this xfer page packet completely!\n", 700eb335bc42781ddc19da98a3c74add1013ba08da2Hank Janssen count, vmxferpage_packet->range_cnt + 1); 701fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 702454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Return it to the freelist */ 70353d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang spin_lock_irqsave(&net_device->recv_pkt_list_lock, flags); 70421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman for (i = count; i != 0; i--) { 70592ec0893ad0996a534a5b605659d3ca31cf5dfd9Milan Dadok list_move_tail(listHead.next, 70653d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang &net_device->recv_pkt_list); 707fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 70853d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang spin_unlock_irqrestore(&net_device->recv_pkt_list_lock, 70921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman flags); 710fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 7115a71ae303c0f82968d93d86724c1d94d753b34d7Haiyang Zhang netvsc_send_recv_completion(device, 712415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang vmxferpage_packet->d.trans_id); 713fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 714fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen return; 715fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 716fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 717454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Remove the 1st packet to represent the xfer page packet itself */ 71885799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang xferpage_packet = (struct xferpage_packet *)listHead.next; 71972a2f5bd53bf83302f4dcfe8500d4ec440545d27Haiyang Zhang list_del(&xferpage_packet->list_ent); 720d29274efb73735c6a94f20214b1e4ea994da8848Bill Pemberton 72121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman /* This is how much we can satisfy */ 72272a2f5bd53bf83302f4dcfe8500d4ec440545d27Haiyang Zhang xferpage_packet->count = count - 1; 72321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman 724415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang if (xferpage_packet->count != vmxferpage_packet->range_cnt) { 7258bff33ab417f246dac4ab9835be6894eaddfb546Haiyang Zhang netdev_err(ndev, "Needed %d netvsc pkts to satisfy " 726c909ebbd0dcf19c617408c2cfde56c4bbd4f6cb4Haiyang Zhang "this xfer page...got %d\n", 727eb335bc42781ddc19da98a3c74add1013ba08da2Hank Janssen vmxferpage_packet->range_cnt, xferpage_packet->count); 728fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 729fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 730454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Each range represents 1 RNDIS pkt that contains 1 ethernet frame */ 73121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman for (i = 0; i < (count - 1); i++) { 73285799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang netvsc_packet = (struct hv_netvsc_packet *)listHead.next; 73372a2f5bd53bf83302f4dcfe8500d4ec440545d27Haiyang Zhang list_del(&netvsc_packet->list_ent); 734fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 735454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Initialize the netvsc packet */ 73672a2f5bd53bf83302f4dcfe8500d4ec440545d27Haiyang Zhang netvsc_packet->xfer_page_pkt = xferpage_packet; 73772a2f5bd53bf83302f4dcfe8500d4ec440545d27Haiyang Zhang netvsc_packet->completion.recv.recv_completion = 7385a71ae303c0f82968d93d86724c1d94d753b34d7Haiyang Zhang netvsc_receive_completion; 73972a2f5bd53bf83302f4dcfe8500d4ec440545d27Haiyang Zhang netvsc_packet->completion.recv.recv_completion_ctx = 74085799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang netvsc_packet; 74172a2f5bd53bf83302f4dcfe8500d4ec440545d27Haiyang Zhang netvsc_packet->device = device; 74221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman /* Save this so that we can send it back */ 74372a2f5bd53bf83302f4dcfe8500d4ec440545d27Haiyang Zhang netvsc_packet->completion.recv.recv_completion_tid = 744415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang vmxferpage_packet->d.trans_id; 745fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 746453263421f88b4a7e508c2e7b639c97e99c5b118Haiyang Zhang netvsc_packet->data = (void *)((unsigned long)net_device-> 747453263421f88b4a7e508c2e7b639c97e99c5b118Haiyang Zhang recv_buf + vmxferpage_packet->ranges[i].byte_offset); 74872a2f5bd53bf83302f4dcfe8500d4ec440545d27Haiyang Zhang netvsc_packet->total_data_buflen = 749415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang vmxferpage_packet->ranges[i].byte_count; 750fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 751454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Pass it to the upper layer */ 752ac6f78590104f01036ae7f1ecc062411a251f756K. Y. Srinivasan rndis_filter_receive(device, netvsc_packet); 753fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 7545a71ae303c0f82968d93d86724c1d94d753b34d7Haiyang Zhang netvsc_receive_completion(netvsc_packet-> 75572a2f5bd53bf83302f4dcfe8500d4ec440545d27Haiyang Zhang completion.recv.recv_completion_ctx); 756fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 757fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 758fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen} 759fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 7605a71ae303c0f82968d93d86724c1d94d753b34d7Haiyang Zhangstatic void netvsc_channel_cb(void *context) 761fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{ 76221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman int ret; 76385799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang struct hv_device *device = context; 76485799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang struct netvsc_device *net_device; 76585799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang u32 bytes_recvd; 76685799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang u64 request_id; 767c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pemberton unsigned char *packet; 7688dc0a06ad1f192ea0c8dbe4d2090206c7d880281Greg Kroah-Hartman struct vmpacket_descriptor *desc; 769c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pemberton unsigned char *buffer; 770c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pemberton int bufferlen = NETVSC_PACKET_SIZE; 7712ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan struct net_device *ndev; 772fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 773c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pemberton packet = kzalloc(NETVSC_PACKET_SIZE * sizeof(unsigned char), 774d70c673153d42e8aefd5ac296c8159ef222d076bTimo Teräs GFP_ATOMIC); 775c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pemberton if (!packet) 776c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pemberton return; 777c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pemberton buffer = packet; 778c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pemberton 7795a71ae303c0f82968d93d86724c1d94d753b34d7Haiyang Zhang net_device = get_inbound_net_device(device); 7802ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan if (!net_device) 781c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pemberton goto out; 7822ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan ndev = net_device->ndev; 783fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 78421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman do { 7859f630068e8ccba24d728f196cb3ddc120ebee38eGreg Kroah-Hartman ret = vmbus_recvpacket_raw(device->channel, buffer, bufferlen, 78685799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang &bytes_recvd, &request_id); 78721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (ret == 0) { 78885799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang if (bytes_recvd > 0) { 78921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman desc = (struct vmpacket_descriptor *)buffer; 790415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang switch (desc->type) { 791415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang case VM_PKT_COMP: 7925a71ae303c0f82968d93d86724c1d94d753b34d7Haiyang Zhang netvsc_send_completion(device, desc); 79321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman break; 79421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman 795415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang case VM_PKT_DATA_USING_XFER_PAGES: 7965a71ae303c0f82968d93d86724c1d94d753b34d7Haiyang Zhang netvsc_receive(device, desc); 79721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman break; 79821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman 79921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman default: 800d9871158718778ff060f08cbee0c61eb23041671Haiyang Zhang netdev_err(ndev, 80121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman "unhandled packet type %d, " 80221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman "tid %llx len %d\n", 803415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang desc->type, request_id, 80485799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang bytes_recvd); 80521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman break; 806fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 807fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 808454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* reset */ 809c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pemberton if (bufferlen > NETVSC_PACKET_SIZE) { 8108c69f52ab3d918be9d91c8202e5321421876ea50Greg Kroah-Hartman kfree(buffer); 811fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen buffer = packet; 812c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pemberton bufferlen = NETVSC_PACKET_SIZE; 813fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 81421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman } else { 815454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* reset */ 816c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pemberton if (bufferlen > NETVSC_PACKET_SIZE) { 8178c69f52ab3d918be9d91c8202e5321421876ea50Greg Kroah-Hartman kfree(buffer); 818fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen buffer = packet; 819c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pemberton bufferlen = NETVSC_PACKET_SIZE; 820fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 821fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 822fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen break; 823fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 8243d5cad97c4be2bfc5cb4e52a0972c6e3bf8c278dK. Y. Srinivasan } else if (ret == -ENOBUFS) { 82521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman /* Handle large packet */ 82685799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang buffer = kmalloc(bytes_recvd, GFP_ATOMIC); 82721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (buffer == NULL) { 828454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Try again next time around */ 829d9871158718778ff060f08cbee0c61eb23041671Haiyang Zhang netdev_err(ndev, 83021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman "unable to allocate buffer of size " 831c909ebbd0dcf19c617408c2cfde56c4bbd4f6cb4Haiyang Zhang "(%d)!!\n", bytes_recvd); 832fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen break; 833fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 834fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 83585799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang bufferlen = bytes_recvd; 836fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 837fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } while (1); 838fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 839c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pembertonout: 840c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pemberton kfree(buffer); 841fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen return; 842fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen} 843af24ce42c51fad4fdc2eb3576b8c0388fd19ed4aHaiyang Zhang 844af24ce42c51fad4fdc2eb3576b8c0388fd19ed4aHaiyang Zhang/* 845b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang * netvsc_device_add - Callback when the device belonging to this 846b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang * driver is added 847b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang */ 8487bd23a4d8737777f41cbbe099a027b582b762581K. Y. Srinivasanint netvsc_device_add(struct hv_device *device, void *additional_info) 849b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang{ 850b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang int ret = 0; 851b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang int i; 852aae23986fd5baaf48c7112612fbff7fb1094ad03K. Y. Srinivasan int ring_size = 853aae23986fd5baaf48c7112612fbff7fb1094ad03K. Y. Srinivasan ((struct netvsc_device_info *)additional_info)->ring_size; 854b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang struct netvsc_device *net_device; 855b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang struct hv_netvsc_packet *packet, *pos; 8562ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan struct net_device *ndev; 857b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang 858b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang net_device = alloc_net_device(device); 859b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang if (!net_device) { 860ace163a85a9a98e7f91db3a23db3f63689038f1eK. Y. Srinivasan ret = -ENOMEM; 861b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang goto cleanup; 862b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang } 863b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang 8642ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan /* 8652ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan * Coming into this function, struct net_device * is 8662ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan * registered as the driver private data. 8672ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan * In alloc_net_device(), we register struct netvsc_device * 8682ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan * as the driver private data and stash away struct net_device * 8692ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan * in struct netvsc_device *. 8702ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan */ 8712ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan ndev = net_device->ndev; 8722ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan 873b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang /* Initialize the NetVSC channel extension */ 874b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang net_device->recv_buf_size = NETVSC_RECEIVE_BUFFER_SIZE; 875b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang spin_lock_init(&net_device->recv_pkt_list_lock); 876b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang 877b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang INIT_LIST_HEAD(&net_device->recv_pkt_list); 878b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang 879b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang for (i = 0; i < NETVSC_RECEIVE_PACKETLIST_COUNT; i++) { 880b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang packet = kzalloc(sizeof(struct hv_netvsc_packet) + 881b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang (NETVSC_RECEIVE_SG_COUNT * 882b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang sizeof(struct hv_page_buffer)), GFP_KERNEL); 883b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang if (!packet) 884b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang break; 885b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang 886b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang list_add_tail(&packet->list_ent, 887b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang &net_device->recv_pkt_list); 888b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang } 88935abb21ace3413de6ea8d5c7750cedfd46111f0cK. Y. Srinivasan init_completion(&net_device->channel_init_wait); 890b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang 891b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang /* Open the channel */ 892aae23986fd5baaf48c7112612fbff7fb1094ad03K. Y. Srinivasan ret = vmbus_open(device->channel, ring_size * PAGE_SIZE, 893aae23986fd5baaf48c7112612fbff7fb1094ad03K. Y. Srinivasan ring_size * PAGE_SIZE, NULL, 0, 894b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang netvsc_channel_cb, device); 895b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang 896b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang if (ret != 0) { 897d9871158718778ff060f08cbee0c61eb23041671Haiyang Zhang netdev_err(ndev, "unable to open channel: %d\n", ret); 898b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang goto cleanup; 899b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang } 900b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang 901b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang /* Channel is opened */ 902c909ebbd0dcf19c617408c2cfde56c4bbd4f6cb4Haiyang Zhang pr_info("hv_netvsc channel opened successfully\n"); 903b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang 904b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang /* Connect with the NetVsp */ 905b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang ret = netvsc_connect_vsp(device); 906b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang if (ret != 0) { 907d9871158718778ff060f08cbee0c61eb23041671Haiyang Zhang netdev_err(ndev, 908c909ebbd0dcf19c617408c2cfde56c4bbd4f6cb4Haiyang Zhang "unable to connect to NetVSP - %d\n", ret); 909b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang goto close; 910b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang } 911b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang 912b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang return ret; 913b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang 914b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhangclose: 915b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang /* Now, we can close the channel safely */ 916b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang vmbus_close(device->channel); 917b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang 918b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhangcleanup: 919b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang 920b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang if (net_device) { 921b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang list_for_each_entry_safe(packet, pos, 922b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang &net_device->recv_pkt_list, 923b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang list_ent) { 924b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang list_del(&packet->list_ent); 925b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang kfree(packet); 926b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang } 927b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang 928356c4657193c8a5b3aff84fe8cdf5ddc64742801K. Y. Srinivasan kfree(net_device); 929b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang } 930b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang 931b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang return ret; 932b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang} 933