netvsc.c revision c6fcf0baa6367fecd3e025253700b64ccff8c1eb
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 */ 215654e932262840f853233317689fc59536226d76Greg Kroah-Hartman#include <linux/kernel.h> 220ffa63b09bf99ce3ee879c7de1c687267a90d20bGreg Kroah-Hartman#include <linux/mm.h> 23b4362c9c1fe8bec487e275f92fdf57c585ac236aGreg Kroah-Hartman#include <linux/delay.h> 2421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman#include <linux/io.h> 255a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 264983b39a0687b00688478e6748b979a02934b234Greg Kroah-Hartman#include "osd.h" 27645954c54287faee983d37705b80e9ae90c63782Greg Kroah-Hartman#include "logging.h" 28fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen#include "NetVsc.h" 29fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen#include "RndisFilter.h" 30fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 31fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 32454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton/* Globals */ 3321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartmanstatic const char *gDriverName = "netvsc"; 34fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 35454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton/* {F8615163-DF3E-46c5-913F-F2D2F965ED0E} */ 36caf26a31b51a148f70113700fd4f9860b5da3931Greg Kroah-Hartmanstatic const struct hv_guid gNetVscDeviceType = { 37caf26a31b51a148f70113700fd4f9860b5da3931Greg Kroah-Hartman .data = { 38caf26a31b51a148f70113700fd4f9860b5da3931Greg Kroah-Hartman 0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46, 39caf26a31b51a148f70113700fd4f9860b5da3931Greg Kroah-Hartman 0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E 40caf26a31b51a148f70113700fd4f9860b5da3931Greg Kroah-Hartman } 41fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen}; 42fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 4321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartmanstatic int NetVscOnDeviceAdd(struct hv_device *Device, void *AdditionalInfo); 4421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman 4521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartmanstatic int NetVscOnDeviceRemove(struct hv_device *Device); 4621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman 4721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartmanstatic void NetVscOnCleanup(struct hv_driver *Driver); 4821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman 4921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartmanstatic void NetVscOnChannelCallback(void *context); 5021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman 5121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartmanstatic int NetVscInitializeSendBufferWithNetVsp(struct hv_device *Device); 5221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman 5321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartmanstatic int NetVscInitializeReceiveBufferWithNetVsp(struct hv_device *Device); 5421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman 55ce9ea4cf49b0ba4c67be71550d6cd955b718e967Greg Kroah-Hartmanstatic int NetVscDestroySendBuffer(struct netvsc_device *NetDevice); 5621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman 57ce9ea4cf49b0ba4c67be71550d6cd955b718e967Greg Kroah-Hartmanstatic int NetVscDestroyReceiveBuffer(struct netvsc_device *NetDevice); 5821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman 5921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartmanstatic int NetVscConnectToVsp(struct hv_device *Device); 6021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman 6121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartmanstatic void NetVscOnSendCompletion(struct hv_device *Device, 6221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman struct vmpacket_descriptor *Packet); 6321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman 6421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartmanstatic int NetVscOnSend(struct hv_device *Device, 6521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman struct hv_netvsc_packet *Packet); 6621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman 6721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartmanstatic void NetVscOnReceive(struct hv_device *Device, 6821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman struct vmpacket_descriptor *Packet); 6921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman 7021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartmanstatic void NetVscOnReceiveCompletion(void *Context); 7121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman 7221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartmanstatic void NetVscSendReceiveCompletion(struct hv_device *Device, 7321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman u64 TransactionId); 7421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman 75fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 76ce9ea4cf49b0ba4c67be71550d6cd955b718e967Greg Kroah-Hartmanstatic struct netvsc_device *AllocNetDevice(struct hv_device *Device) 77fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{ 78ce9ea4cf49b0ba4c67be71550d6cd955b718e967Greg Kroah-Hartman struct netvsc_device *netDevice; 79fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 80ce9ea4cf49b0ba4c67be71550d6cd955b718e967Greg Kroah-Hartman netDevice = kzalloc(sizeof(struct netvsc_device), GFP_KERNEL); 81fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen if (!netDevice) 82fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen return NULL; 83fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 84454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Set to 2 to allow both inbound and outbound traffic */ 85f4888417083723c4f5cbfdf4895653279ffdc31eBill Pemberton atomic_cmpxchg(&netDevice->RefCount, 0, 2); 86fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 87fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen netDevice->Device = Device; 88fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen Device->Extension = netDevice; 89fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 90fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen return netDevice; 91fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen} 92fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 93ce9ea4cf49b0ba4c67be71550d6cd955b718e967Greg Kroah-Hartmanstatic void FreeNetDevice(struct netvsc_device *Device) 94fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{ 95f4888417083723c4f5cbfdf4895653279ffdc31eBill Pemberton ASSERT(atomic_read(&Device->RefCount) == 0); 96fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen Device->Device->Extension = NULL; 978c69f52ab3d918be9d91c8202e5321421876ea50Greg Kroah-Hartman kfree(Device); 98fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen} 99fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 100fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 101454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton/* Get the net device object iff exists and its refcount > 1 */ 102ce9ea4cf49b0ba4c67be71550d6cd955b718e967Greg Kroah-Hartmanstatic struct netvsc_device *GetOutboundNetDevice(struct hv_device *Device) 103fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{ 104ce9ea4cf49b0ba4c67be71550d6cd955b718e967Greg Kroah-Hartman struct netvsc_device *netDevice; 105fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 10621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman netDevice = Device->Extension; 107f4888417083723c4f5cbfdf4895653279ffdc31eBill Pemberton if (netDevice && atomic_read(&netDevice->RefCount) > 1) 108f4888417083723c4f5cbfdf4895653279ffdc31eBill Pemberton atomic_inc(&netDevice->RefCount); 109fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen else 110fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen netDevice = NULL; 111fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 112fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen return netDevice; 113fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen} 114fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 115454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton/* Get the net device object iff exists and its refcount > 0 */ 116ce9ea4cf49b0ba4c67be71550d6cd955b718e967Greg Kroah-Hartmanstatic struct netvsc_device *GetInboundNetDevice(struct hv_device *Device) 117fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{ 118ce9ea4cf49b0ba4c67be71550d6cd955b718e967Greg Kroah-Hartman struct netvsc_device *netDevice; 119fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 12021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman netDevice = Device->Extension; 121f4888417083723c4f5cbfdf4895653279ffdc31eBill Pemberton if (netDevice && atomic_read(&netDevice->RefCount)) 122f4888417083723c4f5cbfdf4895653279ffdc31eBill Pemberton atomic_inc(&netDevice->RefCount); 123fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen else 124fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen netDevice = NULL; 125fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 126fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen return netDevice; 127fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen} 128fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 12921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartmanstatic void PutNetDevice(struct hv_device *Device) 130fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{ 131ce9ea4cf49b0ba4c67be71550d6cd955b718e967Greg Kroah-Hartman struct netvsc_device *netDevice; 132fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 13321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman netDevice = Device->Extension; 134fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen ASSERT(netDevice); 135fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 136f4888417083723c4f5cbfdf4895653279ffdc31eBill Pemberton atomic_dec(&netDevice->RefCount); 137fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen} 138fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 139ce9ea4cf49b0ba4c67be71550d6cd955b718e967Greg Kroah-Hartmanstatic struct netvsc_device *ReleaseOutboundNetDevice(struct hv_device *Device) 140fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{ 141ce9ea4cf49b0ba4c67be71550d6cd955b718e967Greg Kroah-Hartman struct netvsc_device *netDevice; 142fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 14321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman netDevice = Device->Extension; 144fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen if (netDevice == NULL) 145fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen return NULL; 146fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 147454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Busy wait until the ref drop to 2, then set it to 1 */ 148f4888417083723c4f5cbfdf4895653279ffdc31eBill Pemberton while (atomic_cmpxchg(&netDevice->RefCount, 2, 1) != 2) 149b4362c9c1fe8bec487e275f92fdf57c585ac236aGreg Kroah-Hartman udelay(100); 150fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 151fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen return netDevice; 152fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen} 153fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 154ce9ea4cf49b0ba4c67be71550d6cd955b718e967Greg Kroah-Hartmanstatic struct netvsc_device *ReleaseInboundNetDevice(struct hv_device *Device) 155fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{ 156ce9ea4cf49b0ba4c67be71550d6cd955b718e967Greg Kroah-Hartman struct netvsc_device *netDevice; 157fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 15821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman netDevice = Device->Extension; 159fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen if (netDevice == NULL) 160fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen return NULL; 161fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 162454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Busy wait until the ref drop to 1, then set it to 0 */ 163f4888417083723c4f5cbfdf4895653279ffdc31eBill Pemberton while (atomic_cmpxchg(&netDevice->RefCount, 1, 0) != 1) 164b4362c9c1fe8bec487e275f92fdf57c585ac236aGreg Kroah-Hartman udelay(100); 165fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 166fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen Device->Extension = NULL; 167fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen return netDevice; 168fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen} 169fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 1703e18951955797872558dad615851a4ca63b2770eHank Janssen/* 17121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman * NetVscInitialize - Main entry point 17221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman */ 17321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartmanint NetVscInitialize(struct hv_driver *drv) 174fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{ 1757e23a6e9626bf93242712f146a9657d38dda497bGreg Kroah-Hartman struct netvsc_driver *driver = (struct netvsc_driver *)drv; 176fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 177fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_ENTER(NETVSC); 178fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 17921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_DBG(NETVSC, "sizeof(struct hv_netvsc_packet)=%zd, " 18021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman "sizeof(struct nvsp_message)=%zd, " 18121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman "sizeof(struct vmtransfer_page_packet_header)=%zd", 18221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman sizeof(struct hv_netvsc_packet), 18321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman sizeof(struct nvsp_message), 18421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman sizeof(struct vmtransfer_page_packet_header)); 185fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 186454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Make sure we are at least 2 pages since 1 page is used for control */ 187fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen ASSERT(driver->RingBufferSize >= (PAGE_SIZE << 1)); 188fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 189fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen drv->name = gDriverName; 190caf26a31b51a148f70113700fd4f9860b5da3931Greg Kroah-Hartman memcpy(&drv->deviceType, &gNetVscDeviceType, sizeof(struct hv_guid)); 191fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 192454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Make sure it is set by the caller */ 193fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen ASSERT(driver->OnReceiveCallback); 194fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen ASSERT(driver->OnLinkStatusChanged); 195fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 196454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Setup the dispatch table */ 19721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman driver->Base.OnDeviceAdd = NetVscOnDeviceAdd; 19821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman driver->Base.OnDeviceRemove = NetVscOnDeviceRemove; 19921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman driver->Base.OnCleanup = NetVscOnCleanup; 200fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 20121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman driver->OnSend = NetVscOnSend; 202fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 203fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen RndisFilterInit(driver); 204fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 205fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_EXIT(NETVSC); 206fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 20721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman return 0; 208fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen} 209fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 21021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartmanstatic int NetVscInitializeReceiveBufferWithNetVsp(struct hv_device *Device) 211fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{ 21221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman int ret = 0; 213ce9ea4cf49b0ba4c67be71550d6cd955b718e967Greg Kroah-Hartman struct netvsc_device *netDevice; 214223c1aa632dbad672ad9b907e5d5e8f385417945Greg Kroah-Hartman struct nvsp_message *initPacket; 215fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 216fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_ENTER(NETVSC); 217fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 218fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen netDevice = GetOutboundNetDevice(Device); 21921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (!netDevice) { 22021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_ERR(NETVSC, "unable to get net device..." 22121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman "device being destroyed?"); 222fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_EXIT(NETVSC); 223fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen return -1; 224fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 225fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen ASSERT(netDevice->ReceiveBufferSize > 0); 22621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman /* page-size grandularity */ 22721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman ASSERT((netDevice->ReceiveBufferSize & (PAGE_SIZE - 1)) == 0); 228fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 22921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman netDevice->ReceiveBuffer = 23021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman osd_PageAlloc(netDevice->ReceiveBufferSize >> PAGE_SHIFT); 23121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (!netDevice->ReceiveBuffer) { 23221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_ERR(NETVSC, 23321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman "unable to allocate receive buffer of size %d", 23421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman netDevice->ReceiveBufferSize); 235fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen ret = -1; 236fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen goto Cleanup; 237fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 23821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman /* page-aligned buffer */ 23921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman ASSERT(((unsigned long)netDevice->ReceiveBuffer & (PAGE_SIZE - 1)) == 24021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman 0); 241fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 242fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_INFO(NETVSC, "Establishing receive buffer's GPADL..."); 243fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 244454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* 245454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * Establish the gpadl handle for this buffer on this 246454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * channel. Note: This call uses the vmbus connection rather 247454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * than the channel to establish the gpadl handle. 248454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton */ 249fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen ret = Device->Driver->VmbusChannelInterface.EstablishGpadl(Device, 25021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman netDevice->ReceiveBuffer, 25121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman netDevice->ReceiveBufferSize, 25221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman &netDevice->ReceiveBufferGpadlHandle); 25321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (ret != 0) { 25421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_ERR(NETVSC, 25521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman "unable to establish receive buffer's gpadl"); 256fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen goto Cleanup; 257fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 258fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 259bfc30aae73b6be57528059a9e03ce8674320e67bGreg Kroah-Hartman /* osd_WaitEventWait(ext->ChannelInitEvent); */ 260fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 261454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Notify the NetVsp of the gpadl handle */ 262fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_INFO(NETVSC, "Sending NvspMessage1TypeSendReceiveBuffer..."); 263fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 264fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen initPacket = &netDevice->ChannelInitPacket; 265fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 266223c1aa632dbad672ad9b907e5d5e8f385417945Greg Kroah-Hartman memset(initPacket, 0, sizeof(struct nvsp_message)); 267fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 26821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman initPacket->Header.MessageType = NvspMessage1TypeSendReceiveBuffer; 26921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman initPacket->Messages.Version1Messages.SendReceiveBuffer.GpadlHandle = netDevice->ReceiveBufferGpadlHandle; 27021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman initPacket->Messages.Version1Messages.SendReceiveBuffer.Id = NETVSC_RECEIVE_BUFFER_ID; 271fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 272454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Send the gpadl notification request */ 273fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen ret = Device->Driver->VmbusChannelInterface.SendPacket(Device, 27421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman initPacket, 27521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman sizeof(struct nvsp_message), 27621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman (unsigned long)initPacket, 27721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman VmbusPacketTypeDataInBand, 27821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); 27921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (ret != 0) { 28021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_ERR(NETVSC, 28121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman "unable to send receive buffer's gpadl to netvsp"); 282fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen goto Cleanup; 283fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 284fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 285bfc30aae73b6be57528059a9e03ce8674320e67bGreg Kroah-Hartman osd_WaitEventWait(netDevice->ChannelInitEvent); 286fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 287454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Check the response */ 28821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (initPacket->Messages.Version1Messages.SendReceiveBufferComplete.Status != NvspStatusSuccess) { 28921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_ERR(NETVSC, "Unable to complete receive buffer " 29021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman "initialzation with NetVsp - status %d", 29121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman initPacket->Messages.Version1Messages.SendReceiveBufferComplete.Status); 292fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen ret = -1; 293fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen goto Cleanup; 294fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 295fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 296454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Parse the response */ 297fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen ASSERT(netDevice->ReceiveSectionCount == 0); 298fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen ASSERT(netDevice->ReceiveSections == NULL); 299fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 300fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen netDevice->ReceiveSectionCount = initPacket->Messages.Version1Messages.SendReceiveBufferComplete.NumSections; 301fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 302223c1aa632dbad672ad9b907e5d5e8f385417945Greg Kroah-Hartman netDevice->ReceiveSections = kmalloc(netDevice->ReceiveSectionCount * sizeof(struct nvsp_1_receive_buffer_section), GFP_KERNEL); 30321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (netDevice->ReceiveSections == NULL) { 304fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen ret = -1; 305fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen goto Cleanup; 306fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 307fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 308fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen memcpy(netDevice->ReceiveSections, 309fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen initPacket->Messages.Version1Messages.SendReceiveBufferComplete.Sections, 310223c1aa632dbad672ad9b907e5d5e8f385417945Greg Kroah-Hartman netDevice->ReceiveSectionCount * sizeof(struct nvsp_1_receive_buffer_section)); 311fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 31221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_INFO(NETVSC, "Receive sections info (count %d, offset %d, " 31321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman "endoffset %d, suballoc size %d, num suballocs %d)", 31421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman netDevice->ReceiveSectionCount, 31521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman netDevice->ReceiveSections[0].Offset, 31621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman netDevice->ReceiveSections[0].EndOffset, 31721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman netDevice->ReceiveSections[0].SubAllocationSize, 31821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman netDevice->ReceiveSections[0].NumSubAllocations); 319fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 32021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman /* 32121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman * For 1st release, there should only be 1 section that represents the 32221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman * entire receive buffer 32321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman */ 324fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen if (netDevice->ReceiveSectionCount != 1 || 32521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman netDevice->ReceiveSections->Offset != 0) { 326fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen ret = -1; 327fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen goto Cleanup; 328fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 329fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 330fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen goto Exit; 331fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 332fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank JanssenCleanup: 333fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen NetVscDestroyReceiveBuffer(netDevice); 334fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 335fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank JanssenExit: 336fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen PutNetDevice(Device); 337fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_EXIT(NETVSC); 338fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen return ret; 339fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen} 340fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 34121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartmanstatic int NetVscInitializeSendBufferWithNetVsp(struct hv_device *Device) 342fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{ 34321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman int ret = 0; 344ce9ea4cf49b0ba4c67be71550d6cd955b718e967Greg Kroah-Hartman struct netvsc_device *netDevice; 345223c1aa632dbad672ad9b907e5d5e8f385417945Greg Kroah-Hartman struct nvsp_message *initPacket; 346fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 347fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_ENTER(NETVSC); 348fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 349fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen netDevice = GetOutboundNetDevice(Device); 35021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (!netDevice) { 35121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_ERR(NETVSC, "unable to get net device..." 35221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman "device being destroyed?"); 353fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_EXIT(NETVSC); 354fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen return -1; 355fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 356fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen ASSERT(netDevice->SendBufferSize > 0); 35721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman /* page-size grandularity */ 35821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman ASSERT((netDevice->SendBufferSize & (PAGE_SIZE - 1)) == 0); 35921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman 36021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman netDevice->SendBuffer = 36121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman osd_PageAlloc(netDevice->SendBufferSize >> PAGE_SHIFT); 36221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (!netDevice->SendBuffer) { 36321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_ERR(NETVSC, "unable to allocate send buffer of size %d", 36421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman netDevice->SendBufferSize); 365fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen ret = -1; 366fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen goto Cleanup; 367fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 36821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman /* page-aligned buffer */ 36921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman ASSERT(((unsigned long)netDevice->SendBuffer & (PAGE_SIZE - 1)) == 0); 370fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 371fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_INFO(NETVSC, "Establishing send buffer's GPADL..."); 372fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 373454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* 374454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * Establish the gpadl handle for this buffer on this 375454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * channel. Note: This call uses the vmbus connection rather 376454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * than the channel to establish the gpadl handle. 377454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton */ 378fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen ret = Device->Driver->VmbusChannelInterface.EstablishGpadl(Device, 37921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman netDevice->SendBuffer, 38021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman netDevice->SendBufferSize, 38121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman &netDevice->SendBufferGpadlHandle); 38221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (ret != 0) { 383fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_ERR(NETVSC, "unable to establish send buffer's gpadl"); 384fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen goto Cleanup; 385fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 386fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 387bfc30aae73b6be57528059a9e03ce8674320e67bGreg Kroah-Hartman /* osd_WaitEventWait(ext->ChannelInitEvent); */ 388fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 389454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Notify the NetVsp of the gpadl handle */ 390fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_INFO(NETVSC, "Sending NvspMessage1TypeSendSendBuffer..."); 391fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 392fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen initPacket = &netDevice->ChannelInitPacket; 393fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 394223c1aa632dbad672ad9b907e5d5e8f385417945Greg Kroah-Hartman memset(initPacket, 0, sizeof(struct nvsp_message)); 395fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 39621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman initPacket->Header.MessageType = NvspMessage1TypeSendSendBuffer; 39721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman initPacket->Messages.Version1Messages.SendReceiveBuffer.GpadlHandle = netDevice->SendBufferGpadlHandle; 39821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman initPacket->Messages.Version1Messages.SendReceiveBuffer.Id = NETVSC_SEND_BUFFER_ID; 399fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 400454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Send the gpadl notification request */ 401fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen ret = Device->Driver->VmbusChannelInterface.SendPacket(Device, 40221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman initPacket, sizeof(struct nvsp_message), 40321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman (unsigned long)initPacket, 40421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman VmbusPacketTypeDataInBand, 40521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); 40621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (ret != 0) { 40721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_ERR(NETVSC, 40821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman "unable to send receive buffer's gpadl to netvsp"); 409fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen goto Cleanup; 410fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 411fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 412bfc30aae73b6be57528059a9e03ce8674320e67bGreg Kroah-Hartman osd_WaitEventWait(netDevice->ChannelInitEvent); 413fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 414454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Check the response */ 41521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (initPacket->Messages.Version1Messages.SendSendBufferComplete.Status != NvspStatusSuccess) { 41621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_ERR(NETVSC, "Unable to complete send buffer " 41721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman "initialzation with NetVsp - status %d", 41821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman initPacket->Messages.Version1Messages.SendSendBufferComplete.Status); 419fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen ret = -1; 420fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen goto Cleanup; 421fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 422fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 423fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen netDevice->SendSectionSize = initPacket->Messages.Version1Messages.SendSendBufferComplete.SectionSize; 424fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 425fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen goto Exit; 426fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 427fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank JanssenCleanup: 428fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen NetVscDestroySendBuffer(netDevice); 429fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 430fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank JanssenExit: 431fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen PutNetDevice(Device); 432fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_EXIT(NETVSC); 433fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen return ret; 434fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen} 435fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 436ce9ea4cf49b0ba4c67be71550d6cd955b718e967Greg Kroah-Hartmanstatic int NetVscDestroyReceiveBuffer(struct netvsc_device *NetDevice) 437fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{ 438223c1aa632dbad672ad9b907e5d5e8f385417945Greg Kroah-Hartman struct nvsp_message *revokePacket; 43921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman int ret = 0; 440fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 441fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_ENTER(NETVSC); 442fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 443454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* 444454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * If we got a section count, it means we received a 445454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * SendReceiveBufferComplete msg (ie sent 446454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * NvspMessage1TypeSendReceiveBuffer msg) therefore, we need 447454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * to send a revoke msg here 448454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton */ 44921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (NetDevice->ReceiveSectionCount) { 45021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_INFO(NETVSC, 45121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman "Sending NvspMessage1TypeRevokeReceiveBuffer..."); 452fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 453454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Send the revoke receive buffer */ 454fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen revokePacket = &NetDevice->RevokePacket; 455223c1aa632dbad672ad9b907e5d5e8f385417945Greg Kroah-Hartman memset(revokePacket, 0, sizeof(struct nvsp_message)); 456fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 457fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen revokePacket->Header.MessageType = NvspMessage1TypeRevokeReceiveBuffer; 458fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen revokePacket->Messages.Version1Messages.RevokeReceiveBuffer.Id = NETVSC_RECEIVE_BUFFER_ID; 459fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 46021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman ret = NetDevice->Device->Driver->VmbusChannelInterface.SendPacket( 46121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman NetDevice->Device, 46221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman revokePacket, 46321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman sizeof(struct nvsp_message), 46421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman (unsigned long)revokePacket, 46521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman VmbusPacketTypeDataInBand, 0); 466454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* 467454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * If we failed here, we might as well return and 468454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * have a leak rather than continue and a bugchk 469454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton */ 47021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (ret != 0) { 47121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_ERR(NETVSC, "unable to send revoke receive " 47221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman "buffer to netvsp"); 473fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_EXIT(NETVSC); 474fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen return -1; 475fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 476fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 477fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 478454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Teardown the gpadl on the vsp end */ 47921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (NetDevice->ReceiveBufferGpadlHandle) { 480fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_INFO(NETVSC, "Tearing down receive buffer's GPADL..."); 481fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 48221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman ret = NetDevice->Device->Driver->VmbusChannelInterface.TeardownGpadl( 48321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman NetDevice->Device, 48421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman NetDevice->ReceiveBufferGpadlHandle); 485fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 486454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* If we failed here, we might as well return and have a leak rather than continue and a bugchk */ 48721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (ret != 0) { 48821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_ERR(NETVSC, 48921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman "unable to teardown receive buffer's gpadl"); 490fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_EXIT(NETVSC); 491fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen return -1; 492fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 493fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen NetDevice->ReceiveBufferGpadlHandle = 0; 494fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 495fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 49621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (NetDevice->ReceiveBuffer) { 497fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_INFO(NETVSC, "Freeing up receive buffer..."); 498fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 499454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Free up the receive buffer */ 50021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman osd_PageFree(NetDevice->ReceiveBuffer, 50121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman NetDevice->ReceiveBufferSize >> PAGE_SHIFT); 502fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen NetDevice->ReceiveBuffer = NULL; 503fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 504fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 50521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (NetDevice->ReceiveSections) { 50621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman NetDevice->ReceiveSectionCount = 0; 5078c69f52ab3d918be9d91c8202e5321421876ea50Greg Kroah-Hartman kfree(NetDevice->ReceiveSections); 508fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen NetDevice->ReceiveSections = NULL; 509fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 510fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 511fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_EXIT(NETVSC); 512fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 513fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen return ret; 514fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen} 515fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 516ce9ea4cf49b0ba4c67be71550d6cd955b718e967Greg Kroah-Hartmanstatic int NetVscDestroySendBuffer(struct netvsc_device *NetDevice) 517fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{ 518223c1aa632dbad672ad9b907e5d5e8f385417945Greg Kroah-Hartman struct nvsp_message *revokePacket; 51921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman int ret = 0; 520fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 521fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_ENTER(NETVSC); 522fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 523454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* 524454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * If we got a section count, it means we received a 525454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * SendReceiveBufferComplete msg (ie sent 526454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * NvspMessage1TypeSendReceiveBuffer msg) therefore, we need 527454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * to send a revoke msg here 528454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton */ 52921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (NetDevice->SendSectionSize) { 53021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_INFO(NETVSC, 53121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman "Sending NvspMessage1TypeRevokeSendBuffer..."); 532fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 533454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Send the revoke send buffer */ 534fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen revokePacket = &NetDevice->RevokePacket; 535223c1aa632dbad672ad9b907e5d5e8f385417945Greg Kroah-Hartman memset(revokePacket, 0, sizeof(struct nvsp_message)); 536fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 537fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen revokePacket->Header.MessageType = NvspMessage1TypeRevokeSendBuffer; 538fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen revokePacket->Messages.Version1Messages.RevokeSendBuffer.Id = NETVSC_SEND_BUFFER_ID; 539fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 540fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen ret = NetDevice->Device->Driver->VmbusChannelInterface.SendPacket(NetDevice->Device, 54121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman revokePacket, 54221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman sizeof(struct nvsp_message), 54321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman (unsigned long)revokePacket, 54421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman VmbusPacketTypeDataInBand, 0); 54521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman /* 54621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman * If we failed here, we might as well return and have a leak 54721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman * rather than continue and a bugchk 54821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman */ 54921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (ret != 0) { 55021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_ERR(NETVSC, "unable to send revoke send buffer " 55121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman "to netvsp"); 552fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_EXIT(NETVSC); 553fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen return -1; 554fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 555fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 556fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 557454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Teardown the gpadl on the vsp end */ 55821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (NetDevice->SendBufferGpadlHandle) { 559fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_INFO(NETVSC, "Tearing down send buffer's GPADL..."); 560fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 56121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman ret = NetDevice->Device->Driver->VmbusChannelInterface.TeardownGpadl(NetDevice->Device, NetDevice->SendBufferGpadlHandle); 562fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 56321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman /* 56421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman * If we failed here, we might as well return and have a leak 56521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman * rather than continue and a bugchk 56621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman */ 56721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (ret != 0) { 56821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_ERR(NETVSC, "unable to teardown send buffer's " 56921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman "gpadl"); 570fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_EXIT(NETVSC); 571fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen return -1; 572fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 573fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen NetDevice->SendBufferGpadlHandle = 0; 574fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 575fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 57621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (NetDevice->SendBuffer) { 577fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_INFO(NETVSC, "Freeing up send buffer..."); 578fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 579454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Free up the receive buffer */ 58021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman osd_PageFree(NetDevice->SendBuffer, 58121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman NetDevice->SendBufferSize >> PAGE_SHIFT); 582fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen NetDevice->SendBuffer = NULL; 583fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 584fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 585fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_EXIT(NETVSC); 586fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 587fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen return ret; 588fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen} 589fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 590fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 59121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartmanstatic int NetVscConnectToVsp(struct hv_device *Device) 592fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{ 59321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman int ret; 594ce9ea4cf49b0ba4c67be71550d6cd955b718e967Greg Kroah-Hartman struct netvsc_device *netDevice; 595223c1aa632dbad672ad9b907e5d5e8f385417945Greg Kroah-Hartman struct nvsp_message *initPacket; 596fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen int ndisVersion; 597fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 598fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_ENTER(NETVSC); 599fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 600fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen netDevice = GetOutboundNetDevice(Device); 60121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (!netDevice) { 60221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_ERR(NETVSC, "unable to get net device..." 60321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman "device being destroyed?"); 604fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_EXIT(NETVSC); 605fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen return -1; 606fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 607fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 608fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen initPacket = &netDevice->ChannelInitPacket; 609fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 610223c1aa632dbad672ad9b907e5d5e8f385417945Greg Kroah-Hartman memset(initPacket, 0, sizeof(struct nvsp_message)); 611fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen initPacket->Header.MessageType = NvspMessageTypeInit; 61221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman initPacket->Messages.InitMessages.Init.MinProtocolVersion = NVSP_MIN_PROTOCOL_VERSION; 61321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman initPacket->Messages.InitMessages.Init.MaxProtocolVersion = NVSP_MAX_PROTOCOL_VERSION; 614fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 615fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_INFO(NETVSC, "Sending NvspMessageTypeInit..."); 616fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 617454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Send the init request */ 618fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen ret = Device->Driver->VmbusChannelInterface.SendPacket(Device, 61921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman initPacket, 62021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman sizeof(struct nvsp_message), 62121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman (unsigned long)initPacket, 62221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman VmbusPacketTypeDataInBand, 62321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); 62421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman 62521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (ret != 0) { 626fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_ERR(NETVSC, "unable to send NvspMessageTypeInit"); 627fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen goto Cleanup; 628fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 629fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 630bfc30aae73b6be57528059a9e03ce8674320e67bGreg Kroah-Hartman osd_WaitEventWait(netDevice->ChannelInitEvent); 631fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 632454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Now, check the response */ 633454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* ASSERT(initPacket->Messages.InitMessages.InitComplete.MaximumMdlChainLength <= MAX_MULTIPAGE_BUFFER_COUNT); */ 634fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_INFO(NETVSC, "NvspMessageTypeInit status(%d) max mdl chain (%d)", 635fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen initPacket->Messages.InitMessages.InitComplete.Status, 636fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen initPacket->Messages.InitMessages.InitComplete.MaximumMdlChainLength); 637fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 63821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (initPacket->Messages.InitMessages.InitComplete.Status != 63921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman NvspStatusSuccess) { 64021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_ERR(NETVSC, 64121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman "unable to initialize with netvsp (status 0x%x)", 64221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman initPacket->Messages.InitMessages.InitComplete.Status); 643fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen ret = -1; 644fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen goto Cleanup; 645fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 646fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 64721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (initPacket->Messages.InitMessages.InitComplete.NegotiatedProtocolVersion != NVSP_PROTOCOL_VERSION_1) { 64821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_ERR(NETVSC, "unable to initialize with netvsp " 64921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman "(version expected 1 got %d)", 65021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman initPacket->Messages.InitMessages.InitComplete.NegotiatedProtocolVersion); 651fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen ret = -1; 652fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen goto Cleanup; 653fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 654fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_INFO(NETVSC, "Sending NvspMessage1TypeSendNdisVersion..."); 655fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 656454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Send the ndis version */ 657223c1aa632dbad672ad9b907e5d5e8f385417945Greg Kroah-Hartman memset(initPacket, 0, sizeof(struct nvsp_message)); 658fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 65921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman ndisVersion = 0x00050000; 660fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 66121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman initPacket->Header.MessageType = NvspMessage1TypeSendNdisVersion; 66221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman initPacket->Messages.Version1Messages.SendNdisVersion.NdisMajorVersion = 66321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman (ndisVersion & 0xFFFF0000) >> 16; 66421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman initPacket->Messages.Version1Messages.SendNdisVersion.NdisMinorVersion = 66521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman ndisVersion & 0xFFFF; 666fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 667454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Send the init request */ 668fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen ret = Device->Driver->VmbusChannelInterface.SendPacket(Device, 66921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman initPacket, 67021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman sizeof(struct nvsp_message), 67121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman (unsigned long)initPacket, 67221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman VmbusPacketTypeDataInBand, 0); 67321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (ret != 0) { 67421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_ERR(NETVSC, 67521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman "unable to send NvspMessage1TypeSendNdisVersion"); 676fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen ret = -1; 677fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen goto Cleanup; 678fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 679454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* 680454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * BUGBUG - We have to wait for the above msg since the 681454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * netvsp uses KMCL which acknowledges packet (completion 682454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * packet) since our Vmbus always set the 683454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED flag 684454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton */ 685bfc30aae73b6be57528059a9e03ce8674320e67bGreg Kroah-Hartman /* osd_WaitEventWait(NetVscChannel->ChannelInitEvent); */ 686454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton 687454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Post the big receive buffer to NetVSP */ 688fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen ret = NetVscInitializeReceiveBufferWithNetVsp(Device); 689fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen if (ret == 0) 690fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen ret = NetVscInitializeSendBufferWithNetVsp(Device); 691fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 692fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank JanssenCleanup: 693fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen PutNetDevice(Device); 694fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_EXIT(NETVSC); 695fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen return ret; 696fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen} 697fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 698ce9ea4cf49b0ba4c67be71550d6cd955b718e967Greg Kroah-Hartmanstatic void NetVscDisconnectFromVsp(struct netvsc_device *NetDevice) 699fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{ 700fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_ENTER(NETVSC); 701fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 702fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen NetVscDestroyReceiveBuffer(NetDevice); 703fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen NetVscDestroySendBuffer(NetDevice); 704fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 705fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_EXIT(NETVSC); 706fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen} 707fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 7083e18951955797872558dad615851a4ca63b2770eHank Janssen/* 70921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman * NetVscOnDeviceAdd - Callback when the device belonging to this driver is added 71021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman */ 71121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartmanstatic int NetVscOnDeviceAdd(struct hv_device *Device, void *AdditionalInfo) 712fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{ 71321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman int ret = 0; 714fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen int i; 715ce9ea4cf49b0ba4c67be71550d6cd955b718e967Greg Kroah-Hartman struct netvsc_device *netDevice; 716d29274efb73735c6a94f20214b1e4ea994da8848Bill Pemberton struct hv_netvsc_packet *packet, *pos; 71721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman struct netvsc_driver *netDriver = 71821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman (struct netvsc_driver *)Device->Driver; 719fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 720fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_ENTER(NETVSC); 721fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 722fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen netDevice = AllocNetDevice(Device); 72321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (!netDevice) { 724fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen ret = -1; 725fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen goto Cleanup; 726fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 727fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 728fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_DBG(NETVSC, "netvsc channel object allocated - %p", netDevice); 729fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 730454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Initialize the NetVSC channel extension */ 731fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen netDevice->ReceiveBufferSize = NETVSC_RECEIVE_BUFFER_SIZE; 7326436873afce6f20fecc0c5099db899b25e1e6c2bGreg Kroah-Hartman spin_lock_init(&netDevice->receive_packet_list_lock); 733fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 734fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen netDevice->SendBufferSize = NETVSC_SEND_BUFFER_SIZE; 735fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 736d29274efb73735c6a94f20214b1e4ea994da8848Bill Pemberton INIT_LIST_HEAD(&netDevice->ReceivePacketList); 737fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 73821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman for (i = 0; i < NETVSC_RECEIVE_PACKETLIST_COUNT; i++) { 73921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman packet = kzalloc(sizeof(struct hv_netvsc_packet) + 74021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman (NETVSC_RECEIVE_SG_COUNT * 74121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman sizeof(struct hv_page_buffer)), GFP_KERNEL); 74221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (!packet) { 74321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_DBG(NETVSC, "unable to allocate netvsc pkts " 74421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman "for receive pool (wanted %d got %d)", 74521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman NETVSC_RECEIVE_PACKETLIST_COUNT, i); 746fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen break; 747fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 748d29274efb73735c6a94f20214b1e4ea994da8848Bill Pemberton list_add_tail(&packet->ListEntry, 749d29274efb73735c6a94f20214b1e4ea994da8848Bill Pemberton &netDevice->ReceivePacketList); 750fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 751bfc30aae73b6be57528059a9e03ce8674320e67bGreg Kroah-Hartman netDevice->ChannelInitEvent = osd_WaitEventCreate(); 752fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 753454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Open the channel */ 754fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen ret = Device->Driver->VmbusChannelInterface.Open(Device, 75521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman netDriver->RingBufferSize, 75621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman netDriver->RingBufferSize, 75721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman NULL, 0, 75821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman NetVscOnChannelCallback, 75921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman Device); 760fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 76121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (ret != 0) { 762fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_ERR(NETVSC, "unable to open channel: %d", ret); 763fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen ret = -1; 764fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen goto Cleanup; 765fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 766fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 767454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Channel is opened */ 768fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_INFO(NETVSC, "*** NetVSC channel opened successfully! ***"); 769fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 770454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Connect with the NetVsp */ 771fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen ret = NetVscConnectToVsp(Device); 77221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (ret != 0) { 773fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_ERR(NETVSC, "unable to connect to NetVSP - %d", ret); 774fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen ret = -1; 775fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen goto Close; 776fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 777fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 77821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_INFO(NETVSC, "*** NetVSC channel handshake result - %d ***", 77921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman ret); 780fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 781fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_EXIT(NETVSC); 782fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen return ret; 783fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 784fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank JanssenClose: 785454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Now, we can close the channel safely */ 786fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen Device->Driver->VmbusChannelInterface.Close(Device); 787fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 788fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank JanssenCleanup: 789fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 79021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (netDevice) { 791420beac4fcc9efd6f7d838ef7cc5693c58c98015Bill Pemberton kfree(netDevice->ChannelInitEvent); 792fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 793d29274efb73735c6a94f20214b1e4ea994da8848Bill Pemberton list_for_each_entry_safe(packet, pos, 794d29274efb73735c6a94f20214b1e4ea994da8848Bill Pemberton &netDevice->ReceivePacketList, 795d29274efb73735c6a94f20214b1e4ea994da8848Bill Pemberton ListEntry) { 796d29274efb73735c6a94f20214b1e4ea994da8848Bill Pemberton list_del(&packet->ListEntry); 7978c69f52ab3d918be9d91c8202e5321421876ea50Greg Kroah-Hartman kfree(packet); 798fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 799fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 800fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen ReleaseOutboundNetDevice(Device); 801fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen ReleaseInboundNetDevice(Device); 802fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 803fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen FreeNetDevice(netDevice); 804fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 805fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 806fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_EXIT(NETVSC); 807fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen return ret; 808fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen} 809fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 8103e18951955797872558dad615851a4ca63b2770eHank Janssen/* 81121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman * NetVscOnDeviceRemove - Callback when the root bus device is removed 81221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman */ 81321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartmanstatic int NetVscOnDeviceRemove(struct hv_device *Device) 814fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{ 815ce9ea4cf49b0ba4c67be71550d6cd955b718e967Greg Kroah-Hartman struct netvsc_device *netDevice; 816d29274efb73735c6a94f20214b1e4ea994da8848Bill Pemberton struct hv_netvsc_packet *netvscPacket, *pos; 817fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 818fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_ENTER(NETVSC); 819fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 82021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_INFO(NETVSC, "Disabling outbound traffic on net device (%p)...", 82121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman Device->Extension); 822fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 823454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Stop outbound traffic ie sends and receives completions */ 824fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen netDevice = ReleaseOutboundNetDevice(Device); 82521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (!netDevice) { 826fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_ERR(NETVSC, "No net device present!!"); 827fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen return -1; 828fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 829fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 830454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Wait for all send completions */ 83121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman while (atomic_read(&netDevice->NumOutstandingSends)) { 83221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_INFO(NETVSC, "waiting for %d requests to complete...", 83321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman atomic_read(&netDevice->NumOutstandingSends)); 834b4362c9c1fe8bec487e275f92fdf57c585ac236aGreg Kroah-Hartman udelay(100); 835fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 836fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 837fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_INFO(NETVSC, "Disconnecting from netvsp..."); 838fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 839fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen NetVscDisconnectFromVsp(netDevice); 840fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 84121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_INFO(NETVSC, "Disabling inbound traffic on net device (%p)...", 84221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman Device->Extension); 843fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 844454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Stop inbound traffic ie receives and sends completions */ 845fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen netDevice = ReleaseInboundNetDevice(Device); 846fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 847454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* At this point, no one should be accessing netDevice except in here */ 848fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_INFO(NETVSC, "net device (%p) safe to remove", netDevice); 849fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 850454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Now, we can close the channel safely */ 851fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen Device->Driver->VmbusChannelInterface.Close(Device); 852fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 853454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Release all resources */ 854d29274efb73735c6a94f20214b1e4ea994da8848Bill Pemberton list_for_each_entry_safe(netvscPacket, pos, 855d29274efb73735c6a94f20214b1e4ea994da8848Bill Pemberton &netDevice->ReceivePacketList, ListEntry) { 856d29274efb73735c6a94f20214b1e4ea994da8848Bill Pemberton list_del(&netvscPacket->ListEntry); 8578c69f52ab3d918be9d91c8202e5321421876ea50Greg Kroah-Hartman kfree(netvscPacket); 858fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 859fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 860420beac4fcc9efd6f7d838ef7cc5693c58c98015Bill Pemberton kfree(netDevice->ChannelInitEvent); 861fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen FreeNetDevice(netDevice); 862fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 863fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_EXIT(NETVSC); 86421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman return 0; 865fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen} 866fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 8673e18951955797872558dad615851a4ca63b2770eHank Janssen/* 86821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman * NetVscOnCleanup - Perform any cleanup when the driver is removed 86921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman */ 87021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartmanstatic void NetVscOnCleanup(struct hv_driver *drv) 871fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{ 872fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_ENTER(NETVSC); 873fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_EXIT(NETVSC); 874fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen} 875fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 87621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartmanstatic void NetVscOnSendCompletion(struct hv_device *Device, 87721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman struct vmpacket_descriptor *Packet) 878fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{ 879ce9ea4cf49b0ba4c67be71550d6cd955b718e967Greg Kroah-Hartman struct netvsc_device *netDevice; 880223c1aa632dbad672ad9b907e5d5e8f385417945Greg Kroah-Hartman struct nvsp_message *nvspPacket; 8814193d4f41ca771d03d43aa9c38d70a7438e59ca7Nicolas Palix struct hv_netvsc_packet *nvscPacket; 882fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 883fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_ENTER(NETVSC); 884fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 885fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen netDevice = GetInboundNetDevice(Device); 88621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (!netDevice) { 88721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_ERR(NETVSC, "unable to get net device..." 88821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman "device being destroyed?"); 889fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_EXIT(NETVSC); 890fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen return; 891fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 892fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 893223c1aa632dbad672ad9b907e5d5e8f385417945Greg Kroah-Hartman nvspPacket = (struct nvsp_message *)((unsigned long)Packet + (Packet->DataOffset8 << 3)); 894fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 89521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_DBG(NETVSC, "send completion packet - type %d", 89621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman nvspPacket->Header.MessageType); 897fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 89821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if ((nvspPacket->Header.MessageType == NvspMessageTypeInitComplete) || 89921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman (nvspPacket->Header.MessageType == 90021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman NvspMessage1TypeSendReceiveBufferComplete) || 90121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman (nvspPacket->Header.MessageType == 90221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman NvspMessage1TypeSendSendBufferComplete)) { 903454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Copy the response back */ 90421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman memcpy(&netDevice->ChannelInitPacket, nvspPacket, 90521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman sizeof(struct nvsp_message)); 906bfc30aae73b6be57528059a9e03ce8674320e67bGreg Kroah-Hartman osd_WaitEventSet(netDevice->ChannelInitEvent); 90721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman } else if (nvspPacket->Header.MessageType == 90821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman NvspMessage1TypeSendRNDISPacketComplete) { 909454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Get the send context */ 9104193d4f41ca771d03d43aa9c38d70a7438e59ca7Nicolas Palix nvscPacket = (struct hv_netvsc_packet *)(unsigned long)Packet->TransactionId; 911fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen ASSERT(nvscPacket); 912fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 913454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Notify the layer above us */ 914fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen nvscPacket->Completion.Send.OnSendCompletion(nvscPacket->Completion.Send.SendCompletionContext); 915fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 916f4888417083723c4f5cbfdf4895653279ffdc31eBill Pemberton atomic_dec(&netDevice->NumOutstandingSends); 91721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman } else { 91821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_ERR(NETVSC, "Unknown send completion packet type - " 91921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman "%d received!!", nvspPacket->Header.MessageType); 920fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 921fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 922fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen PutNetDevice(Device); 923fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_EXIT(NETVSC); 924fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen} 925fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 92621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartmanstatic int NetVscOnSend(struct hv_device *Device, 92721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman struct hv_netvsc_packet *Packet) 928fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{ 929ce9ea4cf49b0ba4c67be71550d6cd955b718e967Greg Kroah-Hartman struct netvsc_device *netDevice; 93021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman int ret = 0; 931fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 932223c1aa632dbad672ad9b907e5d5e8f385417945Greg Kroah-Hartman struct nvsp_message sendMessage; 933fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 934fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_ENTER(NETVSC); 935fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 936fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen netDevice = GetOutboundNetDevice(Device); 93721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (!netDevice) { 93821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_ERR(NETVSC, "net device (%p) shutting down..." 93921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman "ignoring outbound packets", netDevice); 940fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_EXIT(NETVSC); 941fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen return -2; 942fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 943fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 944fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen sendMessage.Header.MessageType = NvspMessage1TypeSendRNDISPacket; 94521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (Packet->IsDataPacket) { 94621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman /* 0 is RMC_DATA; */ 94721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman sendMessage.Messages.Version1Messages.SendRNDISPacket.ChannelType = 0; 94821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman } else { 94921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman /* 1 is RMC_CONTROL; */ 95021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman sendMessage.Messages.Version1Messages.SendRNDISPacket.ChannelType = 1; 95121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman } 952fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 953454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Not using send buffer section */ 95421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman sendMessage.Messages.Version1Messages.SendRNDISPacket.SendBufferSectionIndex = 0xFFFFFFFF; 95521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman sendMessage.Messages.Version1Messages.SendRNDISPacket.SendBufferSectionSize = 0; 95621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman 95721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (Packet->PageBufferCount) { 95821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman ret = Device->Driver->VmbusChannelInterface.SendPacketPageBuffer( 95921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman Device, Packet->PageBuffers, 96021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman Packet->PageBufferCount, 96121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman &sendMessage, 96221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman sizeof(struct nvsp_message), 96321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman (unsigned long)Packet); 96421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman } else { 965fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen ret = Device->Driver->VmbusChannelInterface.SendPacket(Device, 96621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman &sendMessage, 96721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman sizeof(struct nvsp_message), 96821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman (unsigned long)Packet, 96921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman VmbusPacketTypeDataInBand, 97021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); 971fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 972fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 973fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 974fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen if (ret != 0) 97521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_ERR(NETVSC, "Unable to send packet %p ret %d", 97621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman Packet, ret); 977fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 978f4888417083723c4f5cbfdf4895653279ffdc31eBill Pemberton atomic_inc(&netDevice->NumOutstandingSends); 979fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen PutNetDevice(Device); 980fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 981fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_EXIT(NETVSC); 982fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen return ret; 983fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen} 984fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 98521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartmanstatic void NetVscOnReceive(struct hv_device *Device, 98621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman struct vmpacket_descriptor *Packet) 987fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{ 988ce9ea4cf49b0ba4c67be71550d6cd955b718e967Greg Kroah-Hartman struct netvsc_device *netDevice; 9898dc0a06ad1f192ea0c8dbe4d2090206c7d880281Greg Kroah-Hartman struct vmtransfer_page_packet_header *vmxferpagePacket; 990223c1aa632dbad672ad9b907e5d5e8f385417945Greg Kroah-Hartman struct nvsp_message *nvspPacket; 99121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman struct hv_netvsc_packet *netvscPacket = NULL; 992c4b0bc94828a86cfb6a975b0e0d92dc1cd389565Greg Kroah-Hartman unsigned long start; 993c4b0bc94828a86cfb6a975b0e0d92dc1cd389565Greg Kroah-Hartman unsigned long end, endVirtual; 9947e23a6e9626bf93242712f146a9657d38dda497bGreg Kroah-Hartman /* struct netvsc_driver *netvscDriver; */ 99521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman struct xferpage_packet *xferpagePacket = NULL; 99621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman int i, j; 99721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman int count = 0, bytesRemain = 0; 9986436873afce6f20fecc0c5099db899b25e1e6c2bGreg Kroah-Hartman unsigned long flags; 999d29274efb73735c6a94f20214b1e4ea994da8848Bill Pemberton LIST_HEAD(listHead); 1000fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 1001fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_ENTER(NETVSC); 1002fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 1003fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen netDevice = GetInboundNetDevice(Device); 100421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (!netDevice) { 100521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_ERR(NETVSC, "unable to get net device..." 100621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman "device being destroyed?"); 1007fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_EXIT(NETVSC); 1008fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen return; 1009fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 1010fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 101121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman /* 101221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman * All inbound packets other than send completion should be xfer page 101321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman * packet 101421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman */ 101521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (Packet->Type != VmbusPacketTypeDataUsingTransferPages) { 101621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_ERR(NETVSC, "Unknown packet type received - %d", 101721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman Packet->Type); 1018fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen PutNetDevice(Device); 1019fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen return; 1020fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 1021fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 102221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman nvspPacket = (struct nvsp_message *)((unsigned long)Packet + 102321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman (Packet->DataOffset8 << 3)); 1024fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 1025454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Make sure this is a valid nvsp packet */ 102621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (nvspPacket->Header.MessageType != NvspMessage1TypeSendRNDISPacket) { 102721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_ERR(NETVSC, "Unknown nvsp packet type received - %d", 102821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman nvspPacket->Header.MessageType); 1029fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen PutNetDevice(Device); 1030fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen return; 1031fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 1032fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 103321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_DBG(NETVSC, "NVSP packet received - type %d", 103421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman nvspPacket->Header.MessageType); 1035fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 10368dc0a06ad1f192ea0c8dbe4d2090206c7d880281Greg Kroah-Hartman vmxferpagePacket = (struct vmtransfer_page_packet_header *)Packet; 1037fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 103821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (vmxferpagePacket->TransferPageSetId != NETVSC_RECEIVE_BUFFER_ID) { 103921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_ERR(NETVSC, "Invalid xfer page set id - " 104021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman "expecting %x got %x", NETVSC_RECEIVE_BUFFER_ID, 104121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman vmxferpagePacket->TransferPageSetId); 1042fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen PutNetDevice(Device); 1043fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen return; 1044fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 1045fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 104621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_DBG(NETVSC, "xfer page - range count %d", 104721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman vmxferpagePacket->RangeCount); 1048fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 1049454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* 1050454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * Grab free packets (range count + 1) to represent this xfer 1051454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * page packet. +1 to represent the xfer page packet itself. 1052454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * We grab it here so that we know exactly how many we can 1053454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * fulfil 1054454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton */ 10556436873afce6f20fecc0c5099db899b25e1e6c2bGreg Kroah-Hartman spin_lock_irqsave(&netDevice->receive_packet_list_lock, flags); 1056d29274efb73735c6a94f20214b1e4ea994da8848Bill Pemberton while (!list_empty(&netDevice->ReceivePacketList)) { 105792ec0893ad0996a534a5b605659d3ca31cf5dfd9Milan Dadok list_move_tail(netDevice->ReceivePacketList.next, &listHead); 1058fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen if (++count == vmxferpagePacket->RangeCount + 1) 1059fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen break; 1060fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 10616436873afce6f20fecc0c5099db899b25e1e6c2bGreg Kroah-Hartman spin_unlock_irqrestore(&netDevice->receive_packet_list_lock, flags); 1062fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 1063454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* 1064454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * We need at least 2 netvsc pkts (1 to represent the xfer 1065454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * page and at least 1 for the range) i.e. we can handled 1066454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * some of the xfer page packet ranges... 1067454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton */ 106821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (count < 2) { 106921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_ERR(NETVSC, "Got only %d netvsc pkt...needed %d pkts. " 107021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman "Dropping this xfer page packet completely!", 107121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman count, vmxferpagePacket->RangeCount + 1); 1072fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 1073454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Return it to the freelist */ 10746436873afce6f20fecc0c5099db899b25e1e6c2bGreg Kroah-Hartman spin_lock_irqsave(&netDevice->receive_packet_list_lock, flags); 107521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman for (i = count; i != 0; i--) { 107692ec0893ad0996a534a5b605659d3ca31cf5dfd9Milan Dadok list_move_tail(listHead.next, 1077d29274efb73735c6a94f20214b1e4ea994da8848Bill Pemberton &netDevice->ReceivePacketList); 1078fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 107921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman spin_unlock_irqrestore(&netDevice->receive_packet_list_lock, 108021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman flags); 1081fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 108221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman NetVscSendReceiveCompletion(Device, 108321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman vmxferpagePacket->d.TransactionId); 1084fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 1085fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen PutNetDevice(Device); 1086fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen return; 1087fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 1088fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 1089454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Remove the 1st packet to represent the xfer page packet itself */ 10900686e4f4a2e6f33c418c8d57d9a4fc82b89557b2Lars Lindley xferpagePacket = (struct xferpage_packet *)listHead.next; 1091d29274efb73735c6a94f20214b1e4ea994da8848Bill Pemberton list_del(&xferpagePacket->ListEntry); 1092d29274efb73735c6a94f20214b1e4ea994da8848Bill Pemberton 109321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman /* This is how much we can satisfy */ 109421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman xferpagePacket->Count = count - 1; 109521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman ASSERT(xferpagePacket->Count > 0 && xferpagePacket->Count <= 109621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman vmxferpagePacket->RangeCount); 109721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman 109821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (xferpagePacket->Count != vmxferpagePacket->RangeCount) { 109921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_INFO(NETVSC, "Needed %d netvsc pkts to satisy this xfer " 110021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman "page...got %d", vmxferpagePacket->RangeCount, 110121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman xferpagePacket->Count); 1102fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 1103fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 1104454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Each range represents 1 RNDIS pkt that contains 1 ethernet frame */ 110521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman for (i = 0; i < (count - 1); i++) { 11060686e4f4a2e6f33c418c8d57d9a4fc82b89557b2Lars Lindley netvscPacket = (struct hv_netvsc_packet *)listHead.next; 1107d29274efb73735c6a94f20214b1e4ea994da8848Bill Pemberton list_del(&netvscPacket->ListEntry); 1108fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 1109454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Initialize the netvsc packet */ 1110fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen netvscPacket->XferPagePacket = xferpagePacket; 111121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman netvscPacket->Completion.Recv.OnReceiveCompletion = 111221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman NetVscOnReceiveCompletion; 111321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman netvscPacket->Completion.Recv.ReceiveCompletionContext = 111421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman netvscPacket; 1115fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen netvscPacket->Device = Device; 111621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman /* Save this so that we can send it back */ 111721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman netvscPacket->Completion.Recv.ReceiveCompletionTid = 111821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman vmxferpagePacket->d.TransactionId; 1119fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 112021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman netvscPacket->TotalDataBufferLength = 112121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman vmxferpagePacket->Ranges[i].ByteCount; 1122fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen netvscPacket->PageBufferCount = 1; 1123fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 112421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman ASSERT(vmxferpagePacket->Ranges[i].ByteOffset + 112521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman vmxferpagePacket->Ranges[i].ByteCount < 112621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman netDevice->ReceiveBufferSize); 1127fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 112821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman netvscPacket->PageBuffers[0].Length = 112921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman vmxferpagePacket->Ranges[i].ByteCount; 1130fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 113121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman start = virt_to_phys((void *)((unsigned long)netDevice->ReceiveBuffer + vmxferpagePacket->Ranges[i].ByteOffset)); 1132fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 1133fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen netvscPacket->PageBuffers[0].Pfn = start >> PAGE_SHIFT; 1134c4b0bc94828a86cfb6a975b0e0d92dc1cd389565Greg Kroah-Hartman endVirtual = (unsigned long)netDevice->ReceiveBuffer 1135fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen + vmxferpagePacket->Ranges[i].ByteOffset 113621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman + vmxferpagePacket->Ranges[i].ByteCount - 1; 113721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman end = virt_to_phys((void *)endVirtual); 1138fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 1139454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Calculate the page relative offset */ 114021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman netvscPacket->PageBuffers[0].Offset = 114121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman vmxferpagePacket->Ranges[i].ByteOffset & (PAGE_SIZE - 1); 114221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if ((end >> PAGE_SHIFT) != (start >> PAGE_SHIFT)) { 114321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman /* Handle frame across multiple pages: */ 114421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman netvscPacket->PageBuffers[0].Length = 114521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman (netvscPacket->PageBuffers[0].Pfn << PAGE_SHIFT) 114621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman + PAGE_SIZE - start; 114721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman bytesRemain = netvscPacket->TotalDataBufferLength - 114821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman netvscPacket->PageBuffers[0].Length; 114921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman for (j = 1; j < NETVSC_PACKET_MAXPAGE; j++) { 115021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman netvscPacket->PageBuffers[j].Offset = 0; 115121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (bytesRemain <= PAGE_SIZE) { 115221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman netvscPacket->PageBuffers[j].Length = bytesRemain; 115321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman bytesRemain = 0; 115421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman } else { 115521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman netvscPacket->PageBuffers[j].Length = PAGE_SIZE; 115621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman bytesRemain -= PAGE_SIZE; 115721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman } 115821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman netvscPacket->PageBuffers[j].Pfn = 115921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman virt_to_phys((void *)(endVirtual - bytesRemain)) >> PAGE_SHIFT; 116021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman netvscPacket->PageBufferCount++; 116121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (bytesRemain == 0) 116221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman break; 1163fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 116421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman ASSERT(bytesRemain == 0); 1165fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 116621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_DBG(NETVSC, "[%d] - (abs offset %u len %u) => " 116721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman "(pfn %llx, offset %u, len %u)", i, 116821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman vmxferpagePacket->Ranges[i].ByteOffset, 116921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman vmxferpagePacket->Ranges[i].ByteCount, 117021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman netvscPacket->PageBuffers[0].Pfn, 117121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman netvscPacket->PageBuffers[0].Offset, 117221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman netvscPacket->PageBuffers[0].Length); 1173fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 1174454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Pass it to the upper layer */ 11757e23a6e9626bf93242712f146a9657d38dda497bGreg Kroah-Hartman ((struct netvsc_driver *)Device->Driver)->OnReceiveCallback(Device, netvscPacket); 1176fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 1177fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen NetVscOnReceiveCompletion(netvscPacket->Completion.Recv.ReceiveCompletionContext); 1178fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 1179fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 1180d29274efb73735c6a94f20214b1e4ea994da8848Bill Pemberton ASSERT(list_empty(&listHead)); 1181fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 1182fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen PutNetDevice(Device); 1183fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_EXIT(NETVSC); 1184fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen} 1185fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 118621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartmanstatic void NetVscSendReceiveCompletion(struct hv_device *Device, 118721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman u64 TransactionId) 1188fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{ 1189223c1aa632dbad672ad9b907e5d5e8f385417945Greg Kroah-Hartman struct nvsp_message recvcompMessage; 119021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman int retries = 0; 119121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman int ret; 1192fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 119321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_DBG(NETVSC, "Sending receive completion pkt - %llx", 119421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman TransactionId); 1195fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 119621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman recvcompMessage.Header.MessageType = 119721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman NvspMessage1TypeSendRNDISPacketComplete; 1198fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 1199454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* FIXME: Pass in the status */ 1200fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen recvcompMessage.Messages.Version1Messages.SendRNDISPacketComplete.Status = NvspStatusSuccess; 1201fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 1202fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssenretry_send_cmplt: 1203454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Send the completion */ 1204fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen ret = Device->Driver->VmbusChannelInterface.SendPacket(Device, 120521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman &recvcompMessage, 120621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman sizeof(struct nvsp_message), 120721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman TransactionId, 120821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman VmbusPacketTypeCompletion, 0); 120921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (ret == 0) { 121021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman /* success */ 1211454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* no-op */ 121221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman } else if (ret == -1) { 121321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman /* no more room...wait a bit and attempt to retry 3 times */ 1214fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen retries++; 121521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_ERR(NETVSC, "unable to send receive completion pkt " 121621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman "(tid %llx)...retrying %d", TransactionId, retries); 1217fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 121821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (retries < 4) { 1219b4362c9c1fe8bec487e275f92fdf57c585ac236aGreg Kroah-Hartman udelay(100); 1220fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen goto retry_send_cmplt; 122121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman } else { 122221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_ERR(NETVSC, "unable to send receive completion " 122321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman "pkt (tid %llx)...give up retrying", 122421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman TransactionId); 1225fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 122621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman } else { 122721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_ERR(NETVSC, "unable to send receive completion pkt - " 122821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman "%llx", TransactionId); 1229fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 1230fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen} 1231fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 1232454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton/* Send a receive completion packet to RNDIS device (ie NetVsp) */ 123321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartmanstatic void NetVscOnReceiveCompletion(void *Context) 1234fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{ 123521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman struct hv_netvsc_packet *packet = Context; 123621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman struct hv_device *device = (struct hv_device *)packet->Device; 1237ce9ea4cf49b0ba4c67be71550d6cd955b718e967Greg Kroah-Hartman struct netvsc_device *netDevice; 123821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman u64 transactionId = 0; 12390e727613ac6e1648d681a75d794862225c801d4bGreg Kroah-Hartman bool fSendReceiveComp = false; 12406436873afce6f20fecc0c5099db899b25e1e6c2bGreg Kroah-Hartman unsigned long flags; 1241fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 1242fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_ENTER(NETVSC); 1243fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 1244fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen ASSERT(packet->XferPagePacket); 1245fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 124621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman /* 124721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman * Even though it seems logical to do a GetOutboundNetDevice() here to 124821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman * send out receive completion, we are using GetInboundNetDevice() 124921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman * since we may have disable outbound traffic already. 125021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman */ 1251fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen netDevice = GetInboundNetDevice(device); 125221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (!netDevice) { 125321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_ERR(NETVSC, "unable to get net device..." 125421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman "device being destroyed?"); 1255fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_EXIT(NETVSC); 1256fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen return; 1257fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 1258fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 1259454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Overloading use of the lock. */ 12606436873afce6f20fecc0c5099db899b25e1e6c2bGreg Kroah-Hartman spin_lock_irqsave(&netDevice->receive_packet_list_lock, flags); 1261fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 1262fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen ASSERT(packet->XferPagePacket->Count > 0); 1263fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen packet->XferPagePacket->Count--; 1264fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 126521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman /* 126621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman * Last one in the line that represent 1 xfer page packet. 126721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman * Return the xfer page packet itself to the freelist 126821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman */ 126921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (packet->XferPagePacket->Count == 0) { 12700e727613ac6e1648d681a75d794862225c801d4bGreg Kroah-Hartman fSendReceiveComp = true; 1271fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen transactionId = packet->Completion.Recv.ReceiveCompletionTid; 1272d29274efb73735c6a94f20214b1e4ea994da8848Bill Pemberton list_add_tail(&packet->XferPagePacket->ListEntry, 1273d29274efb73735c6a94f20214b1e4ea994da8848Bill Pemberton &netDevice->ReceivePacketList); 1274fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 1275fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 1276fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 1277454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Put the packet back */ 1278d29274efb73735c6a94f20214b1e4ea994da8848Bill Pemberton list_add_tail(&packet->ListEntry, &netDevice->ReceivePacketList); 12796436873afce6f20fecc0c5099db899b25e1e6c2bGreg Kroah-Hartman spin_unlock_irqrestore(&netDevice->receive_packet_list_lock, flags); 1280fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 1281454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Send a receive completion for the xfer page packet */ 1282fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen if (fSendReceiveComp) 1283fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen NetVscSendReceiveCompletion(device, transactionId); 1284fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 1285fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen PutNetDevice(device); 1286fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_EXIT(NETVSC); 1287fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen} 1288fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 128921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartmanvoid NetVscOnChannelCallback(void *Context) 1290fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{ 129121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman int ret; 129221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman struct hv_device *device = Context; 1293ce9ea4cf49b0ba4c67be71550d6cd955b718e967Greg Kroah-Hartman struct netvsc_device *netDevice; 12944d64311468a90d4ab1e83c62d63b27da598b73eaGreg Kroah-Hartman u32 bytesRecvd; 129559471438ccbebafb0d63baf8b818d0ca692f882aGreg Kroah-Hartman u64 requestId; 1296c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pemberton unsigned char *packet; 12978dc0a06ad1f192ea0c8dbe4d2090206c7d880281Greg Kroah-Hartman struct vmpacket_descriptor *desc; 1298c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pemberton unsigned char *buffer; 1299c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pemberton int bufferlen = NETVSC_PACKET_SIZE; 1300fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 1301fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 1302fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_ENTER(NETVSC); 1303fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 1304fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen ASSERT(device); 1305fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 1306c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pemberton packet = kzalloc(NETVSC_PACKET_SIZE * sizeof(unsigned char), 1307c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pemberton GFP_KERNEL); 1308c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pemberton if (!packet) 1309c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pemberton return; 1310c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pemberton buffer = packet; 1311c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pemberton 1312fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen netDevice = GetInboundNetDevice(device); 131321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (!netDevice) { 131421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_ERR(NETVSC, "net device (%p) shutting down..." 131521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman "ignoring inbound packets", netDevice); 1316fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_EXIT(NETVSC); 1317c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pemberton goto out; 1318fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 1319fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 132021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman do { 132121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman ret = device->Driver->VmbusChannelInterface.RecvPacketRaw( 132221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman device, buffer, bufferlen, 132321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman &bytesRecvd, &requestId); 132421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (ret == 0) { 132521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (bytesRecvd > 0) { 132621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_DBG(NETVSC, "receive %d bytes, tid %llx", 132721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman bytesRecvd, requestId); 132821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman 132921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman desc = (struct vmpacket_descriptor *)buffer; 133021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman switch (desc->Type) { 133121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman case VmbusPacketTypeCompletion: 133221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman NetVscOnSendCompletion(device, desc); 133321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman break; 133421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman 133521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman case VmbusPacketTypeDataUsingTransferPages: 133621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman NetVscOnReceive(device, desc); 133721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman break; 133821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman 133921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman default: 134021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_ERR(NETVSC, 134121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman "unhandled packet type %d, " 134221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman "tid %llx len %d\n", 134321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman desc->Type, requestId, 134421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman bytesRecvd); 134521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman break; 1346fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 1347fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 1348454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* reset */ 1349c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pemberton if (bufferlen > NETVSC_PACKET_SIZE) { 13508c69f52ab3d918be9d91c8202e5321421876ea50Greg Kroah-Hartman kfree(buffer); 1351fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen buffer = packet; 1352c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pemberton bufferlen = NETVSC_PACKET_SIZE; 1353fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 135421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman } else { 1355454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* reset */ 1356c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pemberton if (bufferlen > NETVSC_PACKET_SIZE) { 13578c69f52ab3d918be9d91c8202e5321421876ea50Greg Kroah-Hartman kfree(buffer); 1358fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen buffer = packet; 1359c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pemberton bufferlen = NETVSC_PACKET_SIZE; 1360fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 1361fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 1362fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen break; 1363fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 136421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman } else if (ret == -2) { 136521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman /* Handle large packet */ 13660a72f3cf9f53ae0f4f1c6e05bb081d99b5d72db2Greg Kroah-Hartman buffer = kmalloc(bytesRecvd, GFP_ATOMIC); 136721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman if (buffer == NULL) { 1368454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Try again next time around */ 136921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman DPRINT_ERR(NETVSC, 137021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman "unable to allocate buffer of size " 137121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman "(%d)!!", bytesRecvd); 1372fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen break; 1373fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 1374fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 1375fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen bufferlen = bytesRecvd; 137621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman } else { 1377fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen ASSERT(0); 1378fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } 1379fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen } while (1); 1380fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen 1381fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen PutNetDevice(device); 1382fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen DPRINT_EXIT(NETVSC); 1383c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pembertonout: 1384c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pemberton kfree(buffer); 1385fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen return; 1386fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen} 1387