13e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen/* 23e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * 33e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * Copyright (c) 2009, Microsoft Corporation. 43e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * 53e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * This program is free software; you can redistribute it and/or modify it 63e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * under the terms and conditions of the GNU General Public License, 73e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * version 2, as published by the Free Software Foundation. 83e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * 93e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * This program is distributed in the hope it will be useful, but WITHOUT 103e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 113e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 123e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * more details. 133e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * 143e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * You should have received a copy of the GNU General Public License along with 153e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 163e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * Place - Suite 330, Boston, MA 02111-1307 USA. 173e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * 183e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * Authors: 193e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * Haiyang Zhang <haiyangz@microsoft.com> 203e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * Hank Janssen <hjanssen@microsoft.com> 213e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen * 223e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen */ 230a46618d58c90f93e8b8e9a18062d1691b70297eHank Janssen#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 240a46618d58c90f93e8b8e9a18062d1691b70297eHank Janssen 25a0086dc512ba6c2161dcf48195daf177ad0c3615Greg Kroah-Hartman#include <linux/kernel.h> 260c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan#include <linux/sched.h> 270c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan#include <linux/wait.h> 285289d3d160e8d5c63974502696ab5def71891f18K. Y. Srinivasan#include <linux/delay.h> 29a0086dc512ba6c2161dcf48195daf177ad0c3615Greg Kroah-Hartman#include <linux/mm.h> 305a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 31a0086dc512ba6c2161dcf48195daf177ad0c3615Greg Kroah-Hartman#include <linux/vmalloc.h> 3246a971913611a23478283931460a95be962ce329Greg Kroah-Hartman#include <linux/hyperv.h> 33407dd1644302ea78fa5d740e67a1c09677aa18a4Greg Kroah-Hartman#include <asm/hyperv.h> 340f2a6619eeef158d11832436ce151987f18cb08dK. Y. Srinivasan#include "hyperv_vmbus.h" 353e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 363e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 37da9fcb7260af0cd85351740b526afdc88d4f348aHaiyang Zhangstruct vmbus_connection vmbus_connection = { 38da9fcb7260af0cd85351740b526afdc88d4f348aHaiyang Zhang .conn_state = DISCONNECTED, 39da9fcb7260af0cd85351740b526afdc88d4f348aHaiyang Zhang .next_gpadl_handle = ATOMIC_INIT(0xE1E10), 403e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen}; 413e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 423e18951955797872558dad615851a4ca63b2770eHank Janssen/* 43c69776771f5fcc49d9a49580234d3a481409c80eHaiyang Zhang * vmbus_connect - Sends a connect request on the partition service connection 44fd8b85eae9928f84c7780f93b8005b3dee7ccbb2Greg Kroah-Hartman */ 45c69776771f5fcc49d9a49580234d3a481409c80eHaiyang Zhangint vmbus_connect(void) 463e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen{ 47fd8b85eae9928f84c7780f93b8005b3dee7ccbb2Greg Kroah-Hartman int ret = 0; 489568a1931cd2066ed0f2df6f311e86dd851ab452K. Y. Srinivasan int t; 4915b2f6479b5c5220848ba159248665d56694d2f9Haiyang Zhang struct vmbus_channel_msginfo *msginfo = NULL; 5082250213d08689ab34589923be3064bb8f4c1964Greg Kroah-Hartman struct vmbus_channel_initiate_contact *msg; 51dd0813b6f51b33529f37ba43334ac65e82d772e8Greg Kroah-Hartman unsigned long flags; 523e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 53454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Initialize the vmbus connection */ 54da9fcb7260af0cd85351740b526afdc88d4f348aHaiyang Zhang vmbus_connection.conn_state = CONNECTING; 55da9fcb7260af0cd85351740b526afdc88d4f348aHaiyang Zhang vmbus_connection.work_queue = create_workqueue("hv_vmbus_con"); 56da9fcb7260af0cd85351740b526afdc88d4f348aHaiyang Zhang if (!vmbus_connection.work_queue) { 573a7546d934ca210ebeb51b1bb5180a3774cee443K. Y. Srinivasan ret = -ENOMEM; 58b0043863a0097c3ebe59f91a91fc25d8e1e575e8K. Y. Srinivasan goto cleanup; 59de65a38406bdf712abc2a845fe1f3db7d1a083edBill Pemberton } 603e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 61da9fcb7260af0cd85351740b526afdc88d4f348aHaiyang Zhang INIT_LIST_HEAD(&vmbus_connection.chn_msg_list); 6215b2f6479b5c5220848ba159248665d56694d2f9Haiyang Zhang spin_lock_init(&vmbus_connection.channelmsg_lock); 633e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 64da9fcb7260af0cd85351740b526afdc88d4f348aHaiyang Zhang INIT_LIST_HEAD(&vmbus_connection.chn_list); 6515b2f6479b5c5220848ba159248665d56694d2f9Haiyang Zhang spin_lock_init(&vmbus_connection.channel_lock); 663e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 67454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* 68454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * Setup the vmbus event connection for channel interrupt 69454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * abstraction stuff 70454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton */ 71df3493e0b3ba72f9b6192a91b24197cac41ce557K. Y. Srinivasan vmbus_connection.int_page = 72df3493e0b3ba72f9b6192a91b24197cac41ce557K. Y. Srinivasan (void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO, 0); 73da9fcb7260af0cd85351740b526afdc88d4f348aHaiyang Zhang if (vmbus_connection.int_page == NULL) { 743a7546d934ca210ebeb51b1bb5180a3774cee443K. Y. Srinivasan ret = -ENOMEM; 75b0043863a0097c3ebe59f91a91fc25d8e1e575e8K. Y. Srinivasan goto cleanup; 763e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen } 773e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 78da9fcb7260af0cd85351740b526afdc88d4f348aHaiyang Zhang vmbus_connection.recv_int_page = vmbus_connection.int_page; 79da9fcb7260af0cd85351740b526afdc88d4f348aHaiyang Zhang vmbus_connection.send_int_page = 80da9fcb7260af0cd85351740b526afdc88d4f348aHaiyang Zhang (void *)((unsigned long)vmbus_connection.int_page + 81fd8b85eae9928f84c7780f93b8005b3dee7ccbb2Greg Kroah-Hartman (PAGE_SIZE >> 1)); 823e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 83fd8b85eae9928f84c7780f93b8005b3dee7ccbb2Greg Kroah-Hartman /* 84fd8b85eae9928f84c7780f93b8005b3dee7ccbb2Greg Kroah-Hartman * Setup the monitor notification facility. The 1st page for 85fd8b85eae9928f84c7780f93b8005b3dee7ccbb2Greg Kroah-Hartman * parent->child and the 2nd page for child->parent 86454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton */ 87df3493e0b3ba72f9b6192a91b24197cac41ce557K. Y. Srinivasan vmbus_connection.monitor_pages = 88df3493e0b3ba72f9b6192a91b24197cac41ce557K. Y. Srinivasan (void *)__get_free_pages((GFP_KERNEL|__GFP_ZERO), 1); 89da9fcb7260af0cd85351740b526afdc88d4f348aHaiyang Zhang if (vmbus_connection.monitor_pages == NULL) { 903a7546d934ca210ebeb51b1bb5180a3774cee443K. Y. Srinivasan ret = -ENOMEM; 91b0043863a0097c3ebe59f91a91fc25d8e1e575e8K. Y. Srinivasan goto cleanup; 923e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen } 933e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 9415b2f6479b5c5220848ba159248665d56694d2f9Haiyang Zhang msginfo = kzalloc(sizeof(*msginfo) + 95fd8b85eae9928f84c7780f93b8005b3dee7ccbb2Greg Kroah-Hartman sizeof(struct vmbus_channel_initiate_contact), 96fd8b85eae9928f84c7780f93b8005b3dee7ccbb2Greg Kroah-Hartman GFP_KERNEL); 9715b2f6479b5c5220848ba159248665d56694d2f9Haiyang Zhang if (msginfo == NULL) { 988cad0af9a1a1882cd00f12f8f7c79690f563b1d7Bill Pemberton ret = -ENOMEM; 99b0043863a0097c3ebe59f91a91fc25d8e1e575e8K. Y. Srinivasan goto cleanup; 1003e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen } 1013e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 1029568a1931cd2066ed0f2df6f311e86dd851ab452K. Y. Srinivasan init_completion(&msginfo->waitevent); 10380d11b2ae26543656f7226b44ed9d6a184766e85Bill Pemberton 10415b2f6479b5c5220848ba159248665d56694d2f9Haiyang Zhang msg = (struct vmbus_channel_initiate_contact *)msginfo->msg; 1053e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 106c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang msg->header.msgtype = CHANNELMSG_INITIATE_CONTACT; 107c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang msg->vmbus_version_requested = VMBUS_REVISION_NUMBER; 108da9fcb7260af0cd85351740b526afdc88d4f348aHaiyang Zhang msg->interrupt_page = virt_to_phys(vmbus_connection.int_page); 109da9fcb7260af0cd85351740b526afdc88d4f348aHaiyang Zhang msg->monitor_page1 = virt_to_phys(vmbus_connection.monitor_pages); 110c50f7fb28400bc4829c26bb4a2d6c06a45e90b1aHaiyang Zhang msg->monitor_page2 = virt_to_phys( 111da9fcb7260af0cd85351740b526afdc88d4f348aHaiyang Zhang (void *)((unsigned long)vmbus_connection.monitor_pages + 112fd8b85eae9928f84c7780f93b8005b3dee7ccbb2Greg Kroah-Hartman PAGE_SIZE)); 1133e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 114454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* 115454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * Add to list before we send the request since we may 116454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * receive the response before returning from this routine 117454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton */ 11815b2f6479b5c5220848ba159248665d56694d2f9Haiyang Zhang spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); 11915b2f6479b5c5220848ba159248665d56694d2f9Haiyang Zhang list_add_tail(&msginfo->msglistentry, 120da9fcb7260af0cd85351740b526afdc88d4f348aHaiyang Zhang &vmbus_connection.chn_msg_list); 12153af545b277508d6b4829e90546cbd1beef536a9Bill Pemberton 12215b2f6479b5c5220848ba159248665d56694d2f9Haiyang Zhang spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); 1233e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 124c69776771f5fcc49d9a49580234d3a481409c80eHaiyang Zhang ret = vmbus_post_msg(msg, 125fd8b85eae9928f84c7780f93b8005b3dee7ccbb2Greg Kroah-Hartman sizeof(struct vmbus_channel_initiate_contact)); 126fd8b85eae9928f84c7780f93b8005b3dee7ccbb2Greg Kroah-Hartman if (ret != 0) { 1270c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); 12815b2f6479b5c5220848ba159248665d56694d2f9Haiyang Zhang list_del(&msginfo->msglistentry); 1290c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, 1300c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan flags); 131b0043863a0097c3ebe59f91a91fc25d8e1e575e8K. Y. Srinivasan goto cleanup; 1323e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen } 1333e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 134454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Wait for the connection response */ 1352dfde9644fe8c4a77f9c73f95b25d6300ca23b5dK. Y. Srinivasan t = wait_for_completion_timeout(&msginfo->waitevent, 5*HZ); 1369568a1931cd2066ed0f2df6f311e86dd851ab452K. Y. Srinivasan if (t == 0) { 1370c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan spin_lock_irqsave(&vmbus_connection.channelmsg_lock, 1380c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan flags); 1390c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan list_del(&msginfo->msglistentry); 1400c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, 1410c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan flags); 1420c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan ret = -ETIMEDOUT; 143b0043863a0097c3ebe59f91a91fc25d8e1e575e8K. Y. Srinivasan goto cleanup; 1440c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan } 1453e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 1460c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); 14715b2f6479b5c5220848ba159248665d56694d2f9Haiyang Zhang list_del(&msginfo->msglistentry); 1480c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); 1493e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 150454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Check if successful */ 15115b2f6479b5c5220848ba159248665d56694d2f9Haiyang Zhang if (msginfo->response.version_response.version_supported) { 152da9fcb7260af0cd85351740b526afdc88d4f348aHaiyang Zhang vmbus_connection.conn_state = CONNECTED; 153fd8b85eae9928f84c7780f93b8005b3dee7ccbb2Greg Kroah-Hartman } else { 1540a46618d58c90f93e8b8e9a18062d1691b70297eHank Janssen pr_err("Unable to connect, " 1550a46618d58c90f93e8b8e9a18062d1691b70297eHank Janssen "Version %d not supported by Hyper-V\n", 1560a46618d58c90f93e8b8e9a18062d1691b70297eHank Janssen VMBUS_REVISION_NUMBER); 1573a7546d934ca210ebeb51b1bb5180a3774cee443K. Y. Srinivasan ret = -ECONNREFUSED; 158b0043863a0097c3ebe59f91a91fc25d8e1e575e8K. Y. Srinivasan goto cleanup; 1593e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen } 1603e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 16115b2f6479b5c5220848ba159248665d56694d2f9Haiyang Zhang kfree(msginfo); 1623e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen return 0; 1633e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 164b0043863a0097c3ebe59f91a91fc25d8e1e575e8K. Y. Srinivasancleanup: 165da9fcb7260af0cd85351740b526afdc88d4f348aHaiyang Zhang vmbus_connection.conn_state = DISCONNECTED; 1663e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 167da9fcb7260af0cd85351740b526afdc88d4f348aHaiyang Zhang if (vmbus_connection.work_queue) 168da9fcb7260af0cd85351740b526afdc88d4f348aHaiyang Zhang destroy_workqueue(vmbus_connection.work_queue); 1693e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 170da9fcb7260af0cd85351740b526afdc88d4f348aHaiyang Zhang if (vmbus_connection.int_page) { 171df3493e0b3ba72f9b6192a91b24197cac41ce557K. Y. Srinivasan free_pages((unsigned long)vmbus_connection.int_page, 0); 172da9fcb7260af0cd85351740b526afdc88d4f348aHaiyang Zhang vmbus_connection.int_page = NULL; 1733e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen } 1743e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 175da9fcb7260af0cd85351740b526afdc88d4f348aHaiyang Zhang if (vmbus_connection.monitor_pages) { 176df3493e0b3ba72f9b6192a91b24197cac41ce557K. Y. Srinivasan free_pages((unsigned long)vmbus_connection.monitor_pages, 1); 177da9fcb7260af0cd85351740b526afdc88d4f348aHaiyang Zhang vmbus_connection.monitor_pages = NULL; 1783e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen } 1793e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 180dd9b15dc03075993f63a8a69667a3a8989aedfa1Ilia Mirkin kfree(msginfo); 1813e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 1823e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen return ret; 1833e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen} 1843e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 1853e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 1863e18951955797872558dad615851a4ca63b2770eHank Janssen/* 187c69776771f5fcc49d9a49580234d3a481409c80eHaiyang Zhang * relid2channel - Get the channel object given its 188c69776771f5fcc49d9a49580234d3a481409c80eHaiyang Zhang * child relative id (ie channel id) 189fd8b85eae9928f84c7780f93b8005b3dee7ccbb2Greg Kroah-Hartman */ 190c69776771f5fcc49d9a49580234d3a481409c80eHaiyang Zhangstruct vmbus_channel *relid2channel(u32 relid) 1913e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen{ 192aded7165f262e0f018b23a6cd5cba6e33fd6efd1Greg Kroah-Hartman struct vmbus_channel *channel; 19315b2f6479b5c5220848ba159248665d56694d2f9Haiyang Zhang struct vmbus_channel *found_channel = NULL; 1940f5e44ca6e777660af6b0eb44d4787563932eda8Greg Kroah-Hartman unsigned long flags; 1953e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 19615b2f6479b5c5220848ba159248665d56694d2f9Haiyang Zhang spin_lock_irqsave(&vmbus_connection.channel_lock, flags); 197da9fcb7260af0cd85351740b526afdc88d4f348aHaiyang Zhang list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) { 19815b2f6479b5c5220848ba159248665d56694d2f9Haiyang Zhang if (channel->offermsg.child_relid == relid) { 19915b2f6479b5c5220848ba159248665d56694d2f9Haiyang Zhang found_channel = channel; 2003e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen break; 2013e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen } 2023e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen } 20315b2f6479b5c5220848ba159248665d56694d2f9Haiyang Zhang spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags); 2043e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 20515b2f6479b5c5220848ba159248665d56694d2f9Haiyang Zhang return found_channel; 2063e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen} 2073e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 2083e18951955797872558dad615851a4ca63b2770eHank Janssen/* 209c69776771f5fcc49d9a49580234d3a481409c80eHaiyang Zhang * process_chn_event - Process a channel event notification 210fd8b85eae9928f84c7780f93b8005b3dee7ccbb2Greg Kroah-Hartman */ 21135436487e954d903237cdd2e1b4f8ca6de4dfe61Olaf Heringstatic void process_chn_event(u32 relid) 2123e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen{ 213aded7165f262e0f018b23a6cd5cba6e33fd6efd1Greg Kroah-Hartman struct vmbus_channel *channel; 214dad76bf73fc20b42d020fe5a93dbe4b4868e7681K. Y. Srinivasan unsigned long flags; 2153e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 216454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* 217454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * Find the channel based on this relid and invokes the 218454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton * channel callback to process the event 219454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton */ 220c69776771f5fcc49d9a49580234d3a481409c80eHaiyang Zhang channel = relid2channel(relid); 2213e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 22224326039b9685e8bfb1532932e18cb458f2a3517K. Y. Srinivasan if (!channel) { 22324326039b9685e8bfb1532932e18cb458f2a3517K. Y. Srinivasan pr_err("channel not found for relid - %u\n", relid); 22424326039b9685e8bfb1532932e18cb458f2a3517K. Y. Srinivasan return; 22524326039b9685e8bfb1532932e18cb458f2a3517K. Y. Srinivasan } 22624326039b9685e8bfb1532932e18cb458f2a3517K. Y. Srinivasan 22724326039b9685e8bfb1532932e18cb458f2a3517K. Y. Srinivasan /* 22824326039b9685e8bfb1532932e18cb458f2a3517K. Y. Srinivasan * A channel once created is persistent even when there 22924326039b9685e8bfb1532932e18cb458f2a3517K. Y. Srinivasan * is no driver handling the device. An unloading driver 23024326039b9685e8bfb1532932e18cb458f2a3517K. Y. Srinivasan * sets the onchannel_callback to NULL under the 23124326039b9685e8bfb1532932e18cb458f2a3517K. Y. Srinivasan * protection of the channel inbound_lock. Thus, checking 23224326039b9685e8bfb1532932e18cb458f2a3517K. Y. Srinivasan * and invoking the driver specific callback takes care of 23324326039b9685e8bfb1532932e18cb458f2a3517K. Y. Srinivasan * orderly unloading of the driver. 23424326039b9685e8bfb1532932e18cb458f2a3517K. Y. Srinivasan */ 23524326039b9685e8bfb1532932e18cb458f2a3517K. Y. Srinivasan 236dad76bf73fc20b42d020fe5a93dbe4b4868e7681K. Y. Srinivasan spin_lock_irqsave(&channel->inbound_lock, flags); 23724326039b9685e8bfb1532932e18cb458f2a3517K. Y. Srinivasan if (channel->onchannel_callback != NULL) 238df452fa120cfe0ac6aa4255425b303a9863e3cc1K. Y. Srinivasan channel->onchannel_callback(channel->channel_callback_context); 239d9add43b485538bd1e6c52d8177231ae31143265K. Y. Srinivasan else 24024326039b9685e8bfb1532932e18cb458f2a3517K. Y. Srinivasan pr_err("no channel callback for relid - %u\n", relid); 241d9add43b485538bd1e6c52d8177231ae31143265K. Y. Srinivasan 242dad76bf73fc20b42d020fe5a93dbe4b4868e7681K. Y. Srinivasan spin_unlock_irqrestore(&channel->inbound_lock, flags); 2433e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen} 2443e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 2453e18951955797872558dad615851a4ca63b2770eHank Janssen/* 246c69776771f5fcc49d9a49580234d3a481409c80eHaiyang Zhang * vmbus_on_event - Handler for events 247fd8b85eae9928f84c7780f93b8005b3dee7ccbb2Greg Kroah-Hartman */ 2486de3d6aa9ad455726eb7b689e2d3e57d89374e55K. Y. Srinivasanvoid vmbus_on_event(unsigned long data) 2493e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen{ 25035436487e954d903237cdd2e1b4f8ca6de4dfe61Olaf Hering u32 dword; 25135436487e954d903237cdd2e1b4f8ca6de4dfe61Olaf Hering u32 maxdword = MAX_NUM_CHANNELS_SUPPORTED >> 5; 2523e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen int bit; 25335436487e954d903237cdd2e1b4f8ca6de4dfe61Olaf Hering u32 relid; 254da9fcb7260af0cd85351740b526afdc88d4f348aHaiyang Zhang u32 *recv_int_page = vmbus_connection.recv_int_page; 2553e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 256454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Check events */ 257242b45aa8d93f7fc46ed551db9eb06cc33da7167Olaf Hering if (!recv_int_page) 258242b45aa8d93f7fc46ed551db9eb06cc33da7167Olaf Hering return; 259242b45aa8d93f7fc46ed551db9eb06cc33da7167Olaf Hering for (dword = 0; dword < maxdword; dword++) { 260242b45aa8d93f7fc46ed551db9eb06cc33da7167Olaf Hering if (!recv_int_page[dword]) 261242b45aa8d93f7fc46ed551db9eb06cc33da7167Olaf Hering continue; 262242b45aa8d93f7fc46ed551db9eb06cc33da7167Olaf Hering for (bit = 0; bit < 32; bit++) { 263d9add43b485538bd1e6c52d8177231ae31143265K. Y. Srinivasan if (sync_test_and_clear_bit(bit, 264d9add43b485538bd1e6c52d8177231ae31143265K. Y. Srinivasan (unsigned long *)&recv_int_page[dword])) { 265242b45aa8d93f7fc46ed551db9eb06cc33da7167Olaf Hering relid = (dword << 5) + bit; 266242b45aa8d93f7fc46ed551db9eb06cc33da7167Olaf Hering 267d9add43b485538bd1e6c52d8177231ae31143265K. Y. Srinivasan if (relid == 0) 2686d81d33059e3a062660fd671ea8842662373dfb9K. Y. Srinivasan /* 2696d81d33059e3a062660fd671ea8842662373dfb9K. Y. Srinivasan * Special case - vmbus 2706d81d33059e3a062660fd671ea8842662373dfb9K. Y. Srinivasan * channel protocol msg 2716d81d33059e3a062660fd671ea8842662373dfb9K. Y. Srinivasan */ 272242b45aa8d93f7fc46ed551db9eb06cc33da7167Olaf Hering continue; 273d9add43b485538bd1e6c52d8177231ae31143265K. Y. Srinivasan 27435436487e954d903237cdd2e1b4f8ca6de4dfe61Olaf Hering process_chn_event(relid); 2753e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen } 276242b45aa8d93f7fc46ed551db9eb06cc33da7167Olaf Hering } 2773e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen } 2783e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen} 2793e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 2803e18951955797872558dad615851a4ca63b2770eHank Janssen/* 281c69776771f5fcc49d9a49580234d3a481409c80eHaiyang Zhang * vmbus_post_msg - Send a msg on the vmbus's message connection 282fd8b85eae9928f84c7780f93b8005b3dee7ccbb2Greg Kroah-Hartman */ 283c69776771f5fcc49d9a49580234d3a481409c80eHaiyang Zhangint vmbus_post_msg(void *buffer, size_t buflen) 2843e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen{ 28515b2f6479b5c5220848ba159248665d56694d2f9Haiyang Zhang union hv_connection_id conn_id; 2865289d3d160e8d5c63974502696ab5def71891f18K. Y. Srinivasan int ret = 0; 2875289d3d160e8d5c63974502696ab5def71891f18K. Y. Srinivasan int retries = 0; 2883e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 28915b2f6479b5c5220848ba159248665d56694d2f9Haiyang Zhang conn_id.asu32 = 0; 29015b2f6479b5c5220848ba159248665d56694d2f9Haiyang Zhang conn_id.u.id = VMBUS_MESSAGE_CONNECTION_ID; 2915289d3d160e8d5c63974502696ab5def71891f18K. Y. Srinivasan 2925289d3d160e8d5c63974502696ab5def71891f18K. Y. Srinivasan /* 2935289d3d160e8d5c63974502696ab5def71891f18K. Y. Srinivasan * hv_post_message() can have transient failures because of 2945289d3d160e8d5c63974502696ab5def71891f18K. Y. Srinivasan * insufficient resources. Retry the operation a couple of 2955289d3d160e8d5c63974502696ab5def71891f18K. Y. Srinivasan * times before giving up. 2965289d3d160e8d5c63974502696ab5def71891f18K. Y. Srinivasan */ 2975289d3d160e8d5c63974502696ab5def71891f18K. Y. Srinivasan while (retries < 3) { 2985289d3d160e8d5c63974502696ab5def71891f18K. Y. Srinivasan ret = hv_post_message(conn_id, 1, buffer, buflen); 2995289d3d160e8d5c63974502696ab5def71891f18K. Y. Srinivasan if (ret != HV_STATUS_INSUFFICIENT_BUFFERS) 3005289d3d160e8d5c63974502696ab5def71891f18K. Y. Srinivasan return ret; 3015289d3d160e8d5c63974502696ab5def71891f18K. Y. Srinivasan retries++; 3025289d3d160e8d5c63974502696ab5def71891f18K. Y. Srinivasan msleep(100); 3035289d3d160e8d5c63974502696ab5def71891f18K. Y. Srinivasan } 3045289d3d160e8d5c63974502696ab5def71891f18K. Y. Srinivasan return ret; 3053e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen} 3063e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen 3073e18951955797872558dad615851a4ca63b2770eHank Janssen/* 308c69776771f5fcc49d9a49580234d3a481409c80eHaiyang Zhang * vmbus_set_event - Send an event notification to the parent 309fd8b85eae9928f84c7780f93b8005b3dee7ccbb2Greg Kroah-Hartman */ 310c69776771f5fcc49d9a49580234d3a481409c80eHaiyang Zhangint vmbus_set_event(u32 child_relid) 3113e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen{ 312454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton /* Each u32 represents 32 channels */ 31322356585712d1ff08fbfed152edd8b386873b238Olaf Hering sync_set_bit(child_relid & 31, 314da9fcb7260af0cd85351740b526afdc88d4f348aHaiyang Zhang (unsigned long *)vmbus_connection.send_int_page + 31515b2f6479b5c5220848ba159248665d56694d2f9Haiyang Zhang (child_relid >> 5)); 3167c369f405bc918f3245c7ee0b0ad6c6b6c750166Bill Pemberton 317d44890c8d2a83116463c230b59b9b9d356aafe85Haiyang Zhang return hv_signal_event(); 3183e7ee4902fe6996048f03433dd111426db3cfa92Hank Janssen} 319