hyperv/ic: Rework framework/message version negotiation.
Submitted by: Hongjiang Zhang <honzhan microsoft com> Modified by: sephe MFC after: 1 week Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D8280
This commit is contained in:
parent
b32eac7211
commit
4852ebe987
@ -40,6 +40,14 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include "vmbus_if.h"
|
||||
|
||||
#define VMBUS_HEARTBEAT_FWVER_MAJOR 3
|
||||
#define VMBUS_HEARTBEAT_FWVER \
|
||||
VMBUS_IC_VERSION(VMBUS_HEARTBEAT_FWVER_MAJOR, 0)
|
||||
|
||||
#define VMBUS_HEARTBEAT_MSGVER_MAJOR 3
|
||||
#define VMBUS_HEARTBEAT_MSGVER \
|
||||
VMBUS_IC_VERSION(VMBUS_HEARTBEAT_MSGVER_MAJOR, 0)
|
||||
|
||||
static const struct vmbus_ic_desc vmbus_heartbeat_descs[] = {
|
||||
{
|
||||
.ic_guid = { .hv_guid = {
|
||||
@ -80,7 +88,8 @@ vmbus_heartbeat_cb(struct vmbus_channel *chan, void *xsc)
|
||||
*/
|
||||
switch (hdr->ic_type) {
|
||||
case VMBUS_ICMSG_TYPE_NEGOTIATE:
|
||||
error = vmbus_ic_negomsg(sc, data, &dlen);
|
||||
error = vmbus_ic_negomsg(sc, data, &dlen,
|
||||
VMBUS_HEARTBEAT_FWVER, VMBUS_HEARTBEAT_MSGVER);
|
||||
if (error)
|
||||
return;
|
||||
break;
|
||||
|
@ -61,7 +61,9 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/mutex.h>
|
||||
|
||||
#include <dev/hyperv/include/hyperv.h>
|
||||
#include <dev/hyperv/include/vmbus.h>
|
||||
#include <dev/hyperv/utilities/hv_utilreg.h>
|
||||
#include <dev/hyperv/utilities/vmbus_icreg.h>
|
||||
|
||||
#include "hv_util.h"
|
||||
#include "unicode.h"
|
||||
@ -74,6 +76,12 @@ __FBSDID("$FreeBSD$");
|
||||
#define KVP_ERROR 1
|
||||
#define kvp_hdr hdr.kvp_hdr
|
||||
|
||||
#define KVP_FWVER_MAJOR 3
|
||||
#define KVP_FWVER VMBUS_IC_VERSION(KVP_FWVER_MAJOR, 0)
|
||||
|
||||
#define KVP_MSGVER_MAJOR 4
|
||||
#define KVP_MSGVER VMBUS_IC_VERSION(KVP_MSGVER_MAJOR, 0)
|
||||
|
||||
/* hv_kvp debug control */
|
||||
static int hv_kvp_log = 0;
|
||||
|
||||
@ -208,52 +216,10 @@ hv_kvp_transaction_init(hv_kvp_sc *sc, uint32_t rcv_len,
|
||||
sc->host_msg_id = request_id;
|
||||
sc->rcv_buf = rcv_buf;
|
||||
sc->host_kvp_msg = (struct hv_kvp_msg *)&rcv_buf[
|
||||
sizeof(struct hv_vmbus_pipe_hdr) +
|
||||
sizeof(struct hv_vmbus_icmsg_hdr)];
|
||||
sizeof(struct hv_vmbus_pipe_hdr) +
|
||||
sizeof(struct hv_vmbus_icmsg_hdr)];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* hv_kvp - version neogtiation function
|
||||
*/
|
||||
static void
|
||||
hv_kvp_negotiate_version(struct hv_vmbus_icmsg_hdr *icmsghdrp, uint8_t *buf)
|
||||
{
|
||||
struct hv_vmbus_icmsg_negotiate *negop;
|
||||
int icframe_vercnt;
|
||||
int icmsg_vercnt;
|
||||
|
||||
icmsghdrp->icmsgsize = 0x10;
|
||||
|
||||
negop = (struct hv_vmbus_icmsg_negotiate *)&buf[
|
||||
sizeof(struct hv_vmbus_pipe_hdr) +
|
||||
sizeof(struct hv_vmbus_icmsg_hdr)];
|
||||
icframe_vercnt = negop->icframe_vercnt;
|
||||
icmsg_vercnt = negop->icmsg_vercnt;
|
||||
|
||||
/*
|
||||
* Select the framework version number we will support
|
||||
*/
|
||||
if ((icframe_vercnt >= 2) && (negop->icversion_data[1].major == 3)) {
|
||||
icframe_vercnt = 3;
|
||||
if (icmsg_vercnt > 2)
|
||||
icmsg_vercnt = 4;
|
||||
else
|
||||
icmsg_vercnt = 3;
|
||||
} else {
|
||||
icframe_vercnt = 1;
|
||||
icmsg_vercnt = 1;
|
||||
}
|
||||
|
||||
negop->icframe_vercnt = 1;
|
||||
negop->icmsg_vercnt = 1;
|
||||
negop->icversion_data[0].major = icframe_vercnt;
|
||||
negop->icversion_data[0].minor = 0;
|
||||
negop->icversion_data[1].major = icmsg_vercnt;
|
||||
negop->icversion_data[1].minor = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Convert ip related info in umsg from utf8 to utf16 and store in hmsg
|
||||
*/
|
||||
@ -578,7 +544,8 @@ hv_kvp_respond_host(hv_kvp_sc *sc, int error)
|
||||
error = HV_KVP_E_FAIL;
|
||||
|
||||
hv_icmsg_hdrp->status = error;
|
||||
hv_icmsg_hdrp->icflags = HV_ICMSGHDRFLAG_TRANSACTION | HV_ICMSGHDRFLAG_RESPONSE;
|
||||
hv_icmsg_hdrp->icflags = HV_ICMSGHDRFLAG_TRANSACTION |
|
||||
HV_ICMSGHDRFLAG_RESPONSE;
|
||||
|
||||
error = vmbus_chan_send(vmbus_get_channel(sc->dev),
|
||||
VMBUS_CHANPKT_TYPE_INBAND, 0, sc->rcv_buf, sc->host_msg_len,
|
||||
@ -622,8 +589,8 @@ hv_kvp_process_request(void *context, int pending)
|
||||
uint32_t recvlen = 0;
|
||||
uint64_t requestid;
|
||||
struct hv_vmbus_icmsg_hdr *icmsghdrp;
|
||||
int ret = 0;
|
||||
hv_kvp_sc *sc;
|
||||
int ret = 0, error;
|
||||
hv_kvp_sc *sc;
|
||||
|
||||
hv_kvp_log_info("%s: entering hv_kvp_process_request\n", __func__);
|
||||
|
||||
@ -637,14 +604,15 @@ hv_kvp_process_request(void *context, int pending)
|
||||
/* XXX check recvlen to make sure that it contains enough data */
|
||||
|
||||
while ((ret == 0) && (recvlen > 0)) {
|
||||
|
||||
icmsghdrp = (struct hv_vmbus_icmsg_hdr *)
|
||||
&kvp_buf[sizeof(struct hv_vmbus_pipe_hdr)];
|
||||
&kvp_buf[sizeof(struct hv_vmbus_pipe_hdr)];
|
||||
|
||||
hv_kvp_transaction_init(sc, recvlen, requestid, kvp_buf);
|
||||
if (icmsghdrp->icmsgtype == HV_ICMSGTYPE_NEGOTIATE) {
|
||||
hv_kvp_negotiate_version(icmsghdrp, kvp_buf);
|
||||
hv_kvp_respond_host(sc, ret);
|
||||
error = vmbus_ic_negomsg(&sc->util_sc,
|
||||
kvp_buf, &recvlen, KVP_FWVER, KVP_MSGVER);
|
||||
/* XXX handle vmbus_ic_negomsg failure. */
|
||||
hv_kvp_respond_host(sc, error);
|
||||
|
||||
/*
|
||||
* It is ok to not acquire the mutex before setting
|
||||
|
@ -28,7 +28,6 @@
|
||||
|
||||
#ifndef _KVP_H
|
||||
#define _KVP_H
|
||||
|
||||
/*
|
||||
* An implementation of HyperV key value pair (KVP) functionality for FreeBSD
|
||||
*
|
||||
@ -178,9 +177,9 @@ struct hv_kvp_ipaddr_value {
|
||||
}__attribute__((packed));
|
||||
|
||||
struct hv_kvp_hdr {
|
||||
uint8_t operation;
|
||||
uint8_t pool;
|
||||
uint16_t pad;
|
||||
uint8_t operation;
|
||||
uint8_t pool;
|
||||
uint16_t pad;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct hv_kvp_exchg_msg_value {
|
||||
|
@ -41,6 +41,14 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include "vmbus_if.h"
|
||||
|
||||
#define VMBUS_SHUTDOWN_FWVER_MAJOR 3
|
||||
#define VMBUS_SHUTDOWN_FWVER \
|
||||
VMBUS_IC_VERSION(VMBUS_SHUTDOWN_FWVER_MAJOR, 0)
|
||||
|
||||
#define VMBUS_SHUTDOWN_MSGVER_MAJOR 3
|
||||
#define VMBUS_SHUTDOWN_MSGVER \
|
||||
VMBUS_IC_VERSION(VMBUS_SHUTDOWN_MSGVER_MAJOR, 0)
|
||||
|
||||
static const struct vmbus_ic_desc vmbus_shutdown_descs[] = {
|
||||
{
|
||||
.ic_guid = { .hv_guid = {
|
||||
@ -82,7 +90,8 @@ vmbus_shutdown_cb(struct vmbus_channel *chan, void *xsc)
|
||||
*/
|
||||
switch (hdr->ic_type) {
|
||||
case VMBUS_ICMSG_TYPE_NEGOTIATE:
|
||||
error = vmbus_ic_negomsg(sc, data, &dlen);
|
||||
error = vmbus_ic_negomsg(sc, data, &dlen,
|
||||
VMBUS_SHUTDOWN_FWVER, VMBUS_SHUTDOWN_MSGVER);
|
||||
if (error)
|
||||
return;
|
||||
break;
|
||||
|
@ -42,6 +42,14 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include "vmbus_if.h"
|
||||
|
||||
#define VMBUS_TIMESYNC_FWVER_MAJOR 3
|
||||
#define VMBUS_TIMESYNC_FWVER \
|
||||
VMBUS_IC_VERSION(VMBUS_TIMESYNC_FWVER_MAJOR, 0)
|
||||
|
||||
#define VMBUS_TIMESYNC_MSGVER_MAJOR 3
|
||||
#define VMBUS_TIMESYNC_MSGVER \
|
||||
VMBUS_IC_VERSION(VMBUS_TIMESYNC_MSGVER_MAJOR, 0)
|
||||
|
||||
static const struct vmbus_ic_desc vmbus_timesync_descs[] = {
|
||||
{
|
||||
.ic_guid = { .hv_guid = {
|
||||
@ -162,7 +170,8 @@ vmbus_timesync_cb(struct vmbus_channel *chan, void *xsc)
|
||||
*/
|
||||
switch (hdr->ic_type) {
|
||||
case VMBUS_ICMSG_TYPE_NEGOTIATE:
|
||||
error = vmbus_ic_negomsg(sc, data, &dlen);
|
||||
error = vmbus_ic_negomsg(sc, data, &dlen,
|
||||
VMBUS_TIMESYNC_FWVER, VMBUS_TIMESYNC_MSGVER);
|
||||
if (error)
|
||||
return;
|
||||
break;
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <sys/module.h>
|
||||
#include <sys/reboot.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/timetc.h>
|
||||
|
||||
#include <dev/hyperv/include/hyperv.h>
|
||||
@ -53,52 +54,145 @@
|
||||
__offsetof(struct vmbus_icmsg_negotiate, ic_ver[VMBUS_IC_VERCNT])
|
||||
CTASSERT(VMBUS_IC_NEGOSZ < VMBUS_IC_BRSIZE);
|
||||
|
||||
static int vmbus_ic_fwver_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
static int vmbus_ic_msgver_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
|
||||
int
|
||||
vmbus_ic_negomsg(struct hv_util_sc *sc, void *data, int *dlen0)
|
||||
vmbus_ic_negomsg(struct hv_util_sc *sc, void *data, int *dlen0,
|
||||
uint32_t fw_ver, uint32_t msg_ver)
|
||||
{
|
||||
struct vmbus_icmsg_negotiate *nego;
|
||||
int cnt, major, dlen = *dlen0;
|
||||
int i, cnt, dlen = *dlen0, error;
|
||||
uint32_t sel_fw_ver, sel_msg_ver;
|
||||
bool has_fw_ver, has_msg_ver;
|
||||
|
||||
/*
|
||||
* Preliminary message size verification
|
||||
* Preliminary message verification.
|
||||
*/
|
||||
if (dlen < sizeof(*nego)) {
|
||||
device_printf(sc->ic_dev, "truncated ic negotiate, len %d\n",
|
||||
dlen);
|
||||
return EINVAL;
|
||||
return (EINVAL);
|
||||
}
|
||||
nego = data;
|
||||
|
||||
if (nego->ic_fwver_cnt == 0) {
|
||||
device_printf(sc->ic_dev, "ic negotiate does not contain "
|
||||
"framework version %u\n", nego->ic_fwver_cnt);
|
||||
return (EINVAL);
|
||||
}
|
||||
if (nego->ic_msgver_cnt == 0) {
|
||||
device_printf(sc->ic_dev, "ic negotiate does not contain "
|
||||
"message version %u\n", nego->ic_msgver_cnt);
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
cnt = nego->ic_fwver_cnt + nego->ic_msgver_cnt;
|
||||
if (dlen < __offsetof(struct vmbus_icmsg_negotiate, ic_ver[cnt])) {
|
||||
device_printf(sc->ic_dev, "ic negotiate does not contain "
|
||||
"versions %d\n", dlen);
|
||||
return EINVAL;
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
/* Select major version; XXX looks wrong. */
|
||||
if (nego->ic_fwver_cnt >= 2 && VMBUS_ICVER_MAJOR(nego->ic_ver[1]) == 3)
|
||||
major = 3;
|
||||
else
|
||||
major = 1;
|
||||
error = EOPNOTSUPP;
|
||||
|
||||
/* One framework version */
|
||||
/*
|
||||
* Find the best match framework version.
|
||||
*/
|
||||
has_fw_ver = false;
|
||||
for (i = 0; i < nego->ic_fwver_cnt; ++i) {
|
||||
if (VMBUS_ICVER_LE(nego->ic_ver[i], fw_ver)) {
|
||||
if (!has_fw_ver) {
|
||||
sel_fw_ver = nego->ic_ver[i];
|
||||
has_fw_ver = true;
|
||||
} else if (VMBUS_ICVER_GT(nego->ic_ver[i],
|
||||
sel_fw_ver)) {
|
||||
sel_fw_ver = nego->ic_ver[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!has_fw_ver) {
|
||||
device_printf(sc->ic_dev, "failed to select framework "
|
||||
"version\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fine the best match message version.
|
||||
*/
|
||||
has_msg_ver = false;
|
||||
for (i = nego->ic_fwver_cnt;
|
||||
i < nego->ic_fwver_cnt + nego->ic_msgver_cnt; ++i) {
|
||||
if (VMBUS_ICVER_LE(nego->ic_ver[i], msg_ver)) {
|
||||
if (!has_msg_ver) {
|
||||
sel_msg_ver = nego->ic_ver[i];
|
||||
has_msg_ver = true;
|
||||
} else if (VMBUS_ICVER_GT(nego->ic_ver[i],
|
||||
sel_msg_ver)) {
|
||||
sel_msg_ver = nego->ic_ver[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!has_msg_ver) {
|
||||
device_printf(sc->ic_dev, "failed to select message "
|
||||
"version\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
error = 0;
|
||||
done:
|
||||
if (bootverbose || !has_fw_ver || !has_msg_ver) {
|
||||
if (has_fw_ver) {
|
||||
device_printf(sc->ic_dev, "sel framework version: "
|
||||
"%u.%u\n",
|
||||
VMBUS_ICVER_MAJOR(sel_fw_ver),
|
||||
VMBUS_ICVER_MINOR(sel_fw_ver));
|
||||
}
|
||||
for (i = 0; i < nego->ic_fwver_cnt; i++) {
|
||||
device_printf(sc->ic_dev, "supp framework version: "
|
||||
"%u.%u\n",
|
||||
VMBUS_ICVER_MAJOR(nego->ic_ver[i]),
|
||||
VMBUS_ICVER_MINOR(nego->ic_ver[i]));
|
||||
}
|
||||
|
||||
if (has_msg_ver) {
|
||||
device_printf(sc->ic_dev, "sel message version: "
|
||||
"%u.%u\n",
|
||||
VMBUS_ICVER_MAJOR(sel_msg_ver),
|
||||
VMBUS_ICVER_MINOR(sel_msg_ver));
|
||||
}
|
||||
for (i = nego->ic_fwver_cnt;
|
||||
i < nego->ic_fwver_cnt + nego->ic_msgver_cnt; i++) {
|
||||
device_printf(sc->ic_dev, "supp message version: "
|
||||
"%u.%u\n",
|
||||
VMBUS_ICVER_MAJOR(nego->ic_ver[i]),
|
||||
VMBUS_ICVER_MINOR(nego->ic_ver[i]));
|
||||
}
|
||||
}
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
/* Record the selected versions. */
|
||||
sc->ic_fwver = sel_fw_ver;
|
||||
sc->ic_msgver = sel_msg_ver;
|
||||
|
||||
/* One framework version. */
|
||||
nego->ic_fwver_cnt = 1;
|
||||
nego->ic_ver[0] = VMBUS_IC_VERSION(major, 0);
|
||||
nego->ic_ver[0] = sel_fw_ver;
|
||||
|
||||
/* One message version */
|
||||
/* One message version. */
|
||||
nego->ic_msgver_cnt = 1;
|
||||
nego->ic_ver[1] = VMBUS_IC_VERSION(major, 0);
|
||||
nego->ic_ver[1] = sel_msg_ver;
|
||||
|
||||
/* Update data size */
|
||||
/* Update data size. */
|
||||
nego->ic_hdr.ic_dsize = VMBUS_IC_NEGOSZ -
|
||||
sizeof(struct vmbus_icmsg_hdr);
|
||||
|
||||
/* Update total size, if necessary */
|
||||
/* Update total size, if necessary. */
|
||||
if (dlen < VMBUS_IC_NEGOSZ)
|
||||
*dlen0 = VMBUS_IC_NEGOSZ;
|
||||
|
||||
return 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
@ -124,6 +218,8 @@ hv_util_attach(device_t dev, vmbus_chan_callback_t cb)
|
||||
{
|
||||
struct hv_util_sc *sc = device_get_softc(dev);
|
||||
struct vmbus_channel *chan = vmbus_get_channel(dev);
|
||||
struct sysctl_oid_list *child;
|
||||
struct sysctl_ctx_list *ctx;
|
||||
int error;
|
||||
|
||||
sc->ic_dev = dev;
|
||||
@ -146,9 +242,41 @@ hv_util_attach(device_t dev, vmbus_chan_callback_t cb)
|
||||
free(sc->receive_buffer, M_DEVBUF);
|
||||
return (error);
|
||||
}
|
||||
|
||||
ctx = device_get_sysctl_ctx(dev);
|
||||
child = SYSCTL_CHILDREN(device_get_sysctl_tree(dev));
|
||||
SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "fw_version",
|
||||
CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, sc, 0,
|
||||
vmbus_ic_fwver_sysctl, "A", "framework version");
|
||||
SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "msg_version",
|
||||
CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, sc, 0,
|
||||
vmbus_ic_msgver_sysctl, "A", "message version");
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
vmbus_ic_fwver_sysctl(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
struct hv_util_sc *sc = arg1;
|
||||
char verstr[16];
|
||||
|
||||
snprintf(verstr, sizeof(verstr), "%u.%u",
|
||||
VMBUS_ICVER_MAJOR(sc->ic_fwver), VMBUS_ICVER_MINOR(sc->ic_fwver));
|
||||
return sysctl_handle_string(oidp, verstr, sizeof(verstr), req);
|
||||
}
|
||||
|
||||
static int
|
||||
vmbus_ic_msgver_sysctl(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
struct hv_util_sc *sc = arg1;
|
||||
char verstr[16];
|
||||
|
||||
snprintf(verstr, sizeof(verstr), "%u.%u",
|
||||
VMBUS_ICVER_MAJOR(sc->ic_msgver), VMBUS_ICVER_MINOR(sc->ic_msgver));
|
||||
return sysctl_handle_string(oidp, verstr, sizeof(verstr), req);
|
||||
}
|
||||
|
||||
int
|
||||
hv_util_detach(device_t dev)
|
||||
{
|
||||
|
@ -42,6 +42,8 @@ typedef struct hv_util_sc {
|
||||
device_t ic_dev;
|
||||
uint8_t *receive_buffer;
|
||||
int ic_buflen;
|
||||
uint32_t ic_fwver; /* framework version */
|
||||
uint32_t ic_msgver; /* message version */
|
||||
} hv_util_sc;
|
||||
|
||||
struct vmbus_ic_desc {
|
||||
@ -54,6 +56,7 @@ struct vmbus_ic_desc {
|
||||
int hv_util_attach(device_t dev, vmbus_chan_callback_t cb);
|
||||
int hv_util_detach(device_t dev);
|
||||
int vmbus_ic_probe(device_t dev, const struct vmbus_ic_desc descs[]);
|
||||
int vmbus_ic_negomsg(struct hv_util_sc *, void *data, int *dlen);
|
||||
int vmbus_ic_negomsg(struct hv_util_sc *sc, void *data, int *dlen,
|
||||
uint32_t fw_ver, uint32_t msg_ver);
|
||||
|
||||
#endif
|
||||
|
@ -76,16 +76,4 @@ typedef struct hv_vmbus_icmsg_negotiate {
|
||||
hv_vmbus_ic_version icversion_data[1]; /* any size array */
|
||||
} __packed hv_vmbus_icmsg_negotiate;
|
||||
|
||||
typedef struct hv_vmbus_shutdown_msg_data {
|
||||
uint32_t reason_code;
|
||||
uint32_t timeout_seconds;
|
||||
uint32_t flags;
|
||||
uint8_t display_message[2048];
|
||||
} __packed hv_vmbus_shutdown_msg_data;
|
||||
|
||||
typedef struct hv_vmbus_heartbeat_msg_data {
|
||||
uint64_t seq_num;
|
||||
uint32_t reserved[8];
|
||||
} __packed hv_vmbus_heartbeat_msg_data;
|
||||
|
||||
#endif /* !_HV_UTILREG_H_ */
|
||||
|
@ -42,6 +42,12 @@
|
||||
#define VMBUS_IC_VERSION(major, minor) ((major) | (((uint32_t)(minor)) << 16))
|
||||
#define VMBUS_ICVER_MAJOR(ver) ((ver) & 0xffff)
|
||||
#define VMBUS_ICVER_MINOR(ver) (((ver) & 0xffff0000) >> 16)
|
||||
#define VMBUS_ICVER_SWAP(ver) \
|
||||
((VMBUS_ICVER_MAJOR((ver)) << 16) | VMBUS_ICVER_MINOR((ver)))
|
||||
#define VMBUS_ICVER_LE(v1, v2) \
|
||||
(VMBUS_ICVER_SWAP((v1)) <= VMBUS_ICVER_SWAP((v2)))
|
||||
#define VMBUS_ICVER_GT(v1, v2) \
|
||||
(VMBUS_ICVER_SWAP((v1)) > VMBUS_ICVER_SWAP((v2)))
|
||||
|
||||
struct vmbus_pipe_hdr {
|
||||
uint32_t ph_flags;
|
||||
|
Loading…
Reference in New Issue
Block a user