vmbus_heartbeat.c revision 304730
1295958Ssephe/*- 2298446Ssephe * Copyright (c) 2014,2016 Microsoft Corp. 3295958Ssephe * All rights reserved. 4295958Ssephe * 5295958Ssephe * Redistribution and use in source and binary forms, with or without 6295958Ssephe * modification, are permitted provided that the following conditions 7295958Ssephe * are met: 8295958Ssephe * 1. Redistributions of source code must retain the above copyright 9295958Ssephe * notice unmodified, this list of conditions, and the following 10295958Ssephe * disclaimer. 11295958Ssephe * 2. Redistributions in binary form must reproduce the above copyright 12295958Ssephe * notice, this list of conditions and the following disclaimer in the 13295958Ssephe * documentation and/or other materials provided with the distribution. 14295958Ssephe * 15295958Ssephe * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16295958Ssephe * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17295958Ssephe * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18295958Ssephe * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19295958Ssephe * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20295958Ssephe * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21295958Ssephe * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22295958Ssephe * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23295958Ssephe * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24295958Ssephe * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25295958Ssephe * 26295958Ssephe * $FreeBSD: head/sys/dev/hyperv/utilities/hv_heartbeat.c 304730 2016-08-24 04:36:04Z sephe $ 27295958Ssephe */ 28295958Ssephe 29295958Ssephe#include <sys/param.h> 30295958Ssephe#include <sys/kernel.h> 31295958Ssephe#include <sys/bus.h> 32295958Ssephe#include <sys/malloc.h> 33295958Ssephe#include <sys/module.h> 34295958Ssephe#include <sys/timetc.h> 35295958Ssephe#include <sys/syscallsubr.h> 36303422Ssephe#include <sys/systm.h> 37295958Ssephe 38295958Ssephe#include <dev/hyperv/include/hyperv.h> 39302880Ssephe#include <dev/hyperv/include/vmbus.h> 40303067Ssephe#include <dev/hyperv/utilities/hv_utilreg.h> 41295958Ssephe#include "hv_util.h" 42302698Ssephe#include "vmbus_if.h" 43295958Ssephe 44304273Ssephestatic const struct vmbus_ic_desc vmbus_heartbeat_descs[] = { 45304273Ssephe { 46304273Ssephe .ic_guid = { .hv_guid = { 47304273Ssephe 0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e, 48304273Ssephe 0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d} }, 49304273Ssephe .ic_desc = "Hyper-V Heartbeat" 50304273Ssephe }, 51304273Ssephe VMBUS_IC_DESC_END 52304273Ssephe}; 53295958Ssephe 54295958Ssephe/** 55295958Ssephe * Process heartbeat message 56295958Ssephe */ 57295958Ssephestatic void 58303131Ssephehv_heartbeat_cb(struct vmbus_channel *channel, void *context) 59295958Ssephe{ 60295958Ssephe uint8_t* buf; 61302885Ssephe int recvlen; 62295958Ssephe uint64_t requestid; 63295958Ssephe int ret; 64295958Ssephe 65295958Ssephe struct hv_vmbus_heartbeat_msg_data* heartbeat_msg; 66295958Ssephe struct hv_vmbus_icmsg_hdr* icmsghdrp; 67295958Ssephe hv_util_sc *softc; 68295958Ssephe 69295958Ssephe softc = (hv_util_sc*)context; 70297793Spfg buf = softc->receive_buffer; 71295958Ssephe 72303823Ssephe recvlen = softc->ic_buflen; 73302885Ssephe ret = vmbus_chan_recv(channel, buf, &recvlen, &requestid); 74302885Ssephe KASSERT(ret != ENOBUFS, ("hvheartbeat recvbuf is not large enough")); 75302885Ssephe /* XXX check recvlen to make sure that it contains enough data */ 76295958Ssephe 77295958Ssephe if ((ret == 0) && recvlen > 0) { 78295958Ssephe 79295958Ssephe icmsghdrp = (struct hv_vmbus_icmsg_hdr *) 80295958Ssephe &buf[sizeof(struct hv_vmbus_pipe_hdr)]; 81295958Ssephe 82295958Ssephe if (icmsghdrp->icmsgtype == HV_ICMSGTYPE_NEGOTIATE) { 83304730Ssephe int error; 84304730Ssephe 85304730Ssephe error = vmbus_ic_negomsg(softc, buf, recvlen); 86304730Ssephe if (error) 87304730Ssephe return; 88295958Ssephe } else { 89295958Ssephe heartbeat_msg = 90295958Ssephe (struct hv_vmbus_heartbeat_msg_data *) 91295958Ssephe &buf[sizeof(struct hv_vmbus_pipe_hdr) + 92295958Ssephe sizeof(struct hv_vmbus_icmsg_hdr)]; 93295958Ssephe 94295958Ssephe heartbeat_msg->seq_num += 1; 95295958Ssephe } 96295958Ssephe 97295958Ssephe icmsghdrp->icflags = HV_ICMSGHDRFLAG_TRANSACTION | 98295958Ssephe HV_ICMSGHDRFLAG_RESPONSE; 99295958Ssephe 100302882Ssephe vmbus_chan_send(channel, VMBUS_CHANPKT_TYPE_INBAND, 0, 101302882Ssephe buf, recvlen, requestid); 102295958Ssephe } 103295958Ssephe} 104295958Ssephe 105295958Ssephestatic int 106295958Ssephehv_heartbeat_probe(device_t dev) 107295958Ssephe{ 108297220Ssephe 109304273Ssephe return (vmbus_ic_probe(dev, vmbus_heartbeat_descs)); 110295958Ssephe} 111295958Ssephe 112295958Ssephestatic int 113295958Ssephehv_heartbeat_attach(device_t dev) 114295958Ssephe{ 115303824Ssephe return hv_util_attach(dev, hv_heartbeat_cb); 116295958Ssephe} 117295958Ssephe 118295958Ssephestatic device_method_t heartbeat_methods[] = { 119295958Ssephe /* Device interface */ 120295958Ssephe DEVMETHOD(device_probe, hv_heartbeat_probe), 121295958Ssephe DEVMETHOD(device_attach, hv_heartbeat_attach), 122295958Ssephe DEVMETHOD(device_detach, hv_util_detach), 123295958Ssephe { 0, 0 } 124295958Ssephe}; 125295958Ssephe 126295958Ssephestatic driver_t heartbeat_driver = { "hvheartbeat", heartbeat_methods, sizeof(hv_util_sc)}; 127295958Ssephe 128295958Ssephestatic devclass_t heartbeat_devclass; 129295958Ssephe 130295958SsepheDRIVER_MODULE(hv_heartbeat, vmbus, heartbeat_driver, heartbeat_devclass, NULL, NULL); 131295958SsepheMODULE_VERSION(hv_heartbeat, 1); 132295958SsepheMODULE_DEPEND(hv_heartbeat, vmbus, 1, 1, 1); 133