diff options
author | sephe <sephe@FreeBSD.org> | 2016-10-12 02:09:53 +0000 |
---|---|---|
committer | sephe <sephe@FreeBSD.org> | 2016-10-12 02:09:53 +0000 |
commit | abbac49956f6e03854c7d1661c708c28e28eb40d (patch) | |
tree | 4d4112d2008e83d8287c38071c1cd0332f21f4f4 | |
parent | e1a4efcb70d351a2a2be00f017b2ee84aa8ba46b (diff) | |
download | FreeBSD-src-abbac49956f6e03854c7d1661c708c28e28eb40d.zip FreeBSD-src-abbac49956f6e03854c7d1661c708c28e28eb40d.tar.gz |
MFC 302885,302886
302885
hyperv/vmbus: Cleanup channel receiving.
Sponsored by: Microsoft OSTC
Differential Revision: https://reviews.freebsd.org/D7202
302886
hyperv/vmbus: Cleanup channel packet receiving.
Sponsored by: Microsoft OSTC
Differential Revision: https://reviews.freebsd.org/D7204
-rw-r--r-- | sys/dev/hyperv/include/hyperv.h | 36 | ||||
-rw-r--r-- | sys/dev/hyperv/include/vmbus.h | 35 | ||||
-rw-r--r-- | sys/dev/hyperv/netvsc/hv_net_vsc.c | 103 | ||||
-rw-r--r-- | sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c | 26 | ||||
-rw-r--r-- | sys/dev/hyperv/utilities/hv_heartbeat.c | 8 | ||||
-rw-r--r-- | sys/dev/hyperv/utilities/hv_kvp.c | 14 | ||||
-rw-r--r-- | sys/dev/hyperv/utilities/hv_shutdown.c | 7 | ||||
-rw-r--r-- | sys/dev/hyperv/utilities/hv_timesync.c | 6 | ||||
-rw-r--r-- | sys/dev/hyperv/vmbus/hv_channel.c | 100 | ||||
-rw-r--r-- | sys/dev/hyperv/vmbus/vmbus_reg.h | 9 |
10 files changed, 154 insertions, 190 deletions
diff --git a/sys/dev/hyperv/include/hyperv.h b/sys/dev/hyperv/include/hyperv.h index 63b353d..a987b09 100644 --- a/sys/dev/hyperv/include/hyperv.h +++ b/sys/dev/hyperv/include/hyperv.h @@ -90,28 +90,6 @@ struct hyperv_guid { int hyperv_guid2str(const struct hyperv_guid *, char *, size_t); -typedef struct { - uint16_t type; - uint16_t data_offset8; - uint16_t length8; - uint16_t flags; - uint64_t transaction_id; -} __packed hv_vm_packet_descriptor; - -typedef struct { - uint32_t byte_count; - uint32_t byte_offset; -} __packed hv_vm_transfer_page; - -typedef struct { - hv_vm_packet_descriptor d; - uint16_t transfer_page_set_id; - hv_bool_uint8_t sender_owns_set; - uint8_t reserved; - uint32_t range_count; - hv_vm_transfer_page ranges[1]; -} __packed hv_vm_transfer_page_packet_header; - #define HW_MACADDR_LEN 6 /* @@ -298,20 +276,6 @@ hv_set_channel_read_state(hv_vmbus_channel* channel, boolean_t on) channel->ch_flags |= VMBUS_CHAN_FLAG_BATCHREAD; } -int hv_vmbus_channel_recv_packet( - hv_vmbus_channel* channel, - void* buffer, - uint32_t buffer_len, - uint32_t* buffer_actual_len, - uint64_t* request_id); - -int hv_vmbus_channel_recv_packet_raw( - hv_vmbus_channel* channel, - void* buffer, - uint32_t buffer_len, - uint32_t* buffer_actual_len, - uint64_t* request_id); - int hv_vmbus_channel_open( hv_vmbus_channel* channel, uint32_t send_ring_buffer_size, diff --git a/sys/dev/hyperv/include/vmbus.h b/sys/dev/hyperv/include/vmbus.h index 0dbfe6b..891b12a 100644 --- a/sys/dev/hyperv/include/vmbus.h +++ b/sys/dev/hyperv/include/vmbus.h @@ -47,6 +47,19 @@ struct vmbus_gpa { uint64_t gpa_page; } __packed; +#define VMBUS_CHANPKT_SIZE_SHIFT 3 + +#define VMBUS_CHANPKT_GETLEN(pktlen) \ + (((int)(pktlen)) << VMBUS_CHANPKT_SIZE_SHIFT) + +struct vmbus_chanpkt_hdr { + uint16_t cph_type; /* VMBUS_CHANPKT_TYPE_ */ + uint16_t cph_hlen; /* header len, in 8 bytes */ + uint16_t cph_tlen; /* total len, in 8 bytes */ + uint16_t cph_flags; /* VMBUS_CHANPKT_FLAG_ */ + uint64_t cph_xactid; +} __packed; + #define VMBUS_CHANPKT_TYPE_INBAND 0x0006 #define VMBUS_CHANPKT_TYPE_RXBUF 0x0007 #define VMBUS_CHANPKT_TYPE_GPA 0x0009 @@ -54,11 +67,33 @@ struct vmbus_gpa { #define VMBUS_CHANPKT_FLAG_RC 0x0001 /* report completion */ +#define VMBUS_CHANPKT_CONST_DATA(pkt) \ + (const void *)((const uint8_t *)(pkt) + \ + VMBUS_CHANPKT_GETLEN((pkt)->cph_hlen)) + +struct vmbus_rxbuf_desc { + uint32_t rb_len; + uint32_t rb_ofs; +} __packed; + +struct vmbus_chanpkt_rxbuf { + struct vmbus_chanpkt_hdr cp_hdr; + uint16_t cp_rxbuf_id; + uint16_t cp_rsvd; + uint32_t cp_rxbuf_cnt; + struct vmbus_rxbuf_desc cp_rxbuf[]; +} __packed; + #define VMBUS_CHAN_SGLIST_MAX 32 #define VMBUS_CHAN_PRPLIST_MAX 32 struct hv_vmbus_channel; +int vmbus_chan_recv(struct hv_vmbus_channel *chan, void *data, int *dlen, + uint64_t *xactid); +int vmbus_chan_recv_pkt(struct hv_vmbus_channel *chan, + struct vmbus_chanpkt_hdr *pkt, int *pktlen); + int vmbus_chan_send(struct hv_vmbus_channel *chan, uint16_t type, uint16_t flags, void *data, int dlen, uint64_t xactid); int vmbus_chan_send_sglist(struct hv_vmbus_channel *chan, diff --git a/sys/dev/hyperv/netvsc/hv_net_vsc.c b/sys/dev/hyperv/netvsc/hv_net_vsc.c index ff45226..81cb714 100644 --- a/sys/dev/hyperv/netvsc/hv_net_vsc.c +++ b/sys/dev/hyperv/netvsc/hv_net_vsc.c @@ -63,12 +63,12 @@ static int hv_nv_destroy_send_buffer(netvsc_dev *net_dev); static int hv_nv_destroy_rx_buffer(netvsc_dev *net_dev); static int hv_nv_connect_to_vsp(struct hn_softc *sc); static void hv_nv_on_send_completion(netvsc_dev *net_dev, - struct hv_vmbus_channel *, hv_vm_packet_descriptor *pkt); + struct hv_vmbus_channel *, const struct vmbus_chanpkt_hdr *pkt); static void hv_nv_on_receive_completion(struct hv_vmbus_channel *chan, uint64_t tid, uint32_t status); static void hv_nv_on_receive(netvsc_dev *net_dev, struct hn_softc *sc, struct hv_vmbus_channel *chan, - hv_vm_packet_descriptor *pkt); + const struct vmbus_chanpkt_hdr *pkt); /* * @@ -725,13 +725,12 @@ hv_nv_on_device_remove(struct hn_softc *sc, boolean_t destroy_channel) */ static void hv_nv_on_send_completion(netvsc_dev *net_dev, struct hv_vmbus_channel *chan, - hv_vm_packet_descriptor *pkt) + const struct vmbus_chanpkt_hdr *pkt) { - nvsp_msg *nvsp_msg_pkt; + const nvsp_msg *nvsp_msg_pkt; netvsc_packet *net_vsc_pkt; - nvsp_msg_pkt = - (nvsp_msg *)((unsigned long)pkt + (pkt->data_offset8 << 3)); + nvsp_msg_pkt = VMBUS_CHANPKT_CONST_DATA(pkt); if (nvsp_msg_pkt->hdr.msg_type == nvsp_msg_type_init_complete || nvsp_msg_pkt->hdr.msg_type @@ -748,7 +747,7 @@ hv_nv_on_send_completion(netvsc_dev *net_dev, struct hv_vmbus_channel *chan, nvsp_msg_1_type_send_rndis_pkt_complete) { /* Get the send context */ net_vsc_pkt = - (netvsc_packet *)(unsigned long)pkt->transaction_id; + (netvsc_packet *)(unsigned long)pkt->cph_xactid; if (NULL != net_vsc_pkt) { if (net_vsc_pkt->send_buf_section_idx != NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) { @@ -828,10 +827,10 @@ hv_nv_on_send(struct hv_vmbus_channel *chan, netvsc_packet *pkt) */ static void hv_nv_on_receive(netvsc_dev *net_dev, struct hn_softc *sc, - struct hv_vmbus_channel *chan, hv_vm_packet_descriptor *pkt) + struct hv_vmbus_channel *chan, const struct vmbus_chanpkt_hdr *pkthdr) { - hv_vm_transfer_page_packet_header *vm_xfer_page_pkt; - nvsp_msg *nvsp_msg_pkt; + const struct vmbus_chanpkt_rxbuf *pkt; + const nvsp_msg *nvsp_msg_pkt; netvsc_packet vsc_pkt; netvsc_packet *net_vsc_pkt = &vsc_pkt; device_t dev = sc->hn_dev; @@ -839,43 +838,31 @@ hv_nv_on_receive(netvsc_dev *net_dev, struct hn_softc *sc, int i = 0; int status = nvsp_status_success; - /* - * All inbound packets other than send completion should be - * xfer page packet. - */ - if (pkt->type != VMBUS_CHANPKT_TYPE_RXBUF) { - device_printf(dev, "packet type %d is invalid!\n", pkt->type); - return; - } - - nvsp_msg_pkt = (nvsp_msg *)((unsigned long)pkt - + (pkt->data_offset8 << 3)); + nvsp_msg_pkt = VMBUS_CHANPKT_CONST_DATA(pkthdr); /* Make sure this is a valid nvsp packet */ if (nvsp_msg_pkt->hdr.msg_type != nvsp_msg_1_type_send_rndis_pkt) { - device_printf(dev, "packet hdr type %d is invalid!\n", - pkt->type); + device_printf(dev, "packet hdr type %u is invalid!\n", + nvsp_msg_pkt->hdr.msg_type); return; } - vm_xfer_page_pkt = (hv_vm_transfer_page_packet_header *)pkt; + pkt = (const struct vmbus_chanpkt_rxbuf *)pkthdr; - if (vm_xfer_page_pkt->transfer_page_set_id != - NETVSC_RECEIVE_BUFFER_ID) { - device_printf(dev, "transfer_page_set_id %d is invalid!\n", - vm_xfer_page_pkt->transfer_page_set_id); + if (pkt->cp_rxbuf_id != NETVSC_RECEIVE_BUFFER_ID) { + device_printf(dev, "rxbuf_id %d is invalid!\n", + pkt->cp_rxbuf_id); return; } - count = vm_xfer_page_pkt->range_count; + count = pkt->cp_rxbuf_cnt; /* Each range represents 1 RNDIS pkt that contains 1 Ethernet frame */ for (i = 0; i < count; i++) { net_vsc_pkt->status = nvsp_status_success; - net_vsc_pkt->data = (void *)((unsigned long)net_dev->rx_buf + - vm_xfer_page_pkt->ranges[i].byte_offset); - net_vsc_pkt->tot_data_buf_len = - vm_xfer_page_pkt->ranges[i].byte_count; + net_vsc_pkt->data = ((uint8_t *)net_dev->rx_buf + + pkt->cp_rxbuf[i].rb_ofs); + net_vsc_pkt->tot_data_buf_len = pkt->cp_rxbuf[i].rb_len; hv_rf_on_receive(net_dev, chan, net_vsc_pkt); if (net_vsc_pkt->status != nvsp_status_success) { @@ -888,8 +875,7 @@ hv_nv_on_receive(netvsc_dev *net_dev, struct hn_softc *sc, * messages (not just data messages) will trigger a response * message back to the host. */ - hv_nv_on_receive_completion(chan, vm_xfer_page_pkt->d.transaction_id, - status); + hv_nv_on_receive_completion(chan, pkt->cp_hdr.cph_xactid, status); } /* @@ -933,19 +919,19 @@ retry_send_cmplt: * Net VSC receiving vRSS send table from VSP */ static void -hv_nv_send_table(struct hn_softc *sc, hv_vm_packet_descriptor *pkt) +hv_nv_send_table(struct hn_softc *sc, const struct vmbus_chanpkt_hdr *pkt) { netvsc_dev *net_dev; - nvsp_msg *nvsp_msg_pkt; + const nvsp_msg *nvsp_msg_pkt; int i; - uint32_t count, *table; + uint32_t count; + const uint32_t *table; net_dev = hv_nv_get_inbound_net_device(sc); if (!net_dev) return; - nvsp_msg_pkt = - (nvsp_msg *)((unsigned long)pkt + (pkt->data_offset8 << 3)); + nvsp_msg_pkt = VMBUS_CHANPKT_CONST_DATA(pkt); if (nvsp_msg_pkt->hdr.msg_type != nvsp_msg5_type_send_indirection_table) { @@ -961,8 +947,8 @@ hv_nv_send_table(struct hn_softc *sc, hv_vm_packet_descriptor *pkt) return; } - table = (uint32_t *) - ((unsigned long)&nvsp_msg_pkt->msgs.vers_5_msgs.send_table + + table = (const uint32_t *) + ((const uint8_t *)&nvsp_msg_pkt->msgs.vers_5_msgs.send_table + nvsp_msg_pkt->msgs.vers_5_msgs.send_table.offset); for (i = 0; i < count; i++) @@ -979,44 +965,40 @@ hv_nv_on_channel_callback(void *xchan) device_t dev = chan->ch_dev; struct hn_softc *sc = device_get_softc(dev); netvsc_dev *net_dev; - uint32_t bytes_rxed; - uint64_t request_id; - hv_vm_packet_descriptor *desc; - uint8_t *buffer; + void *buffer; int bufferlen = NETVSC_PACKET_SIZE; - int ret = 0; net_dev = hv_nv_get_inbound_net_device(sc); if (net_dev == NULL) return; buffer = chan->hv_chan_rdbuf; - do { - ret = hv_vmbus_channel_recv_packet_raw(chan, - buffer, bufferlen, &bytes_rxed, &request_id); + struct vmbus_chanpkt_hdr *pkt = buffer; + uint32_t bytes_rxed; + int ret; + + bytes_rxed = bufferlen; + ret = vmbus_chan_recv_pkt(chan, pkt, &bytes_rxed); if (ret == 0) { if (bytes_rxed > 0) { - desc = (hv_vm_packet_descriptor *)buffer; - switch (desc->type) { + switch (pkt->cph_type) { case VMBUS_CHANPKT_TYPE_COMP: hv_nv_on_send_completion(net_dev, chan, - desc); + pkt); break; case VMBUS_CHANPKT_TYPE_RXBUF: - hv_nv_on_receive(net_dev, sc, chan, desc); + hv_nv_on_receive(net_dev, sc, chan, pkt); break; case VMBUS_CHANPKT_TYPE_INBAND: - hv_nv_send_table(sc, desc); + hv_nv_send_table(sc, pkt); break; default: device_printf(dev, - "hv_cb recv unknow type %d " - " packet\n", desc->type); + "unknown chan pkt %u\n", + pkt->cph_type); break; } - } else { - break; } } else if (ret == ENOBUFS) { /* Handle large packet */ @@ -1035,6 +1017,9 @@ hv_nv_on_channel_callback(void *xchan) break; } bufferlen = bytes_rxed; + } else { + /* No more packets */ + break; } } while (1); diff --git a/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c b/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c index b65adcb..087768e 100644 --- a/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c +++ b/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c @@ -780,12 +780,10 @@ hv_storvsc_on_channel_callback(void *xchan) struct hv_storvsc_request *request; struct vstor_packet *vstor_packet; - ret = hv_vmbus_channel_recv_packet( - channel, - packet, - roundup2(VSTOR_PKT_SIZE, 8), - &bytes_recvd, - &request_id); + bytes_recvd = roundup2(VSTOR_PKT_SIZE, 8); + ret = vmbus_chan_recv(channel, packet, &bytes_recvd, &request_id); + KASSERT(ret != ENOBUFS, ("storvsc recvbuf is not large enough")); + /* XXX check bytes_recvd to make sure that it contains enough data */ while ((ret == 0) && (bytes_recvd > 0)) { request = (struct hv_storvsc_request *)(uintptr_t)request_id; @@ -819,12 +817,16 @@ hv_storvsc_on_channel_callback(void *xchan) break; } } - ret = hv_vmbus_channel_recv_packet( - channel, - packet, - roundup2(VSTOR_PKT_SIZE, 8), - &bytes_recvd, - &request_id); + + bytes_recvd = roundup2(VSTOR_PKT_SIZE, 8), + ret = vmbus_chan_recv(channel, packet, &bytes_recvd, + &request_id); + KASSERT(ret != ENOBUFS, + ("storvsc recvbuf is not large enough")); + /* + * XXX check bytes_recvd to make sure that it contains + * enough data + */ } } diff --git a/sys/dev/hyperv/utilities/hv_heartbeat.c b/sys/dev/hyperv/utilities/hv_heartbeat.c index cf5c073..660103e 100644 --- a/sys/dev/hyperv/utilities/hv_heartbeat.c +++ b/sys/dev/hyperv/utilities/hv_heartbeat.c @@ -52,7 +52,7 @@ hv_heartbeat_cb(void *context) { uint8_t* buf; hv_vmbus_channel* channel; - uint32_t recvlen; + int recvlen; uint64_t requestid; int ret; @@ -64,8 +64,10 @@ hv_heartbeat_cb(void *context) buf = softc->receive_buffer;; channel = softc->channel; - ret = hv_vmbus_channel_recv_packet(channel, buf, PAGE_SIZE, &recvlen, - &requestid); + recvlen = PAGE_SIZE; + ret = vmbus_chan_recv(channel, buf, &recvlen, &requestid); + KASSERT(ret != ENOBUFS, ("hvheartbeat recvbuf is not large enough")); + /* XXX check recvlen to make sure that it contains enough data */ if ((ret == 0) && recvlen > 0) { diff --git a/sys/dev/hyperv/utilities/hv_kvp.c b/sys/dev/hyperv/utilities/hv_kvp.c index ef87a8c..b0b25c6 100644 --- a/sys/dev/hyperv/utilities/hv_kvp.c +++ b/sys/dev/hyperv/utilities/hv_kvp.c @@ -626,8 +626,10 @@ hv_kvp_process_request(void *context, int pending) kvp_buf = sc->util_sc.receive_buffer;; channel = sc->util_sc.channel; - ret = hv_vmbus_channel_recv_packet(channel, kvp_buf, 2 * PAGE_SIZE, - &recvlen, &requestid); + recvlen = 2 * PAGE_SIZE; + ret = vmbus_chan_recv(channel, kvp_buf, &recvlen, &requestid); + KASSERT(ret != ENOBUFS, ("hvkvp recvbuf is not large enough")); + /* XXX check recvlen to make sure that it contains enough data */ while ((ret == 0) && (recvlen > 0)) { @@ -691,9 +693,11 @@ hv_kvp_process_request(void *context, int pending) /* * Try reading next buffer */ - recvlen = 0; - ret = hv_vmbus_channel_recv_packet(channel, kvp_buf, 2 * PAGE_SIZE, - &recvlen, &requestid); + recvlen = 2 * PAGE_SIZE; + ret = vmbus_chan_recv(channel, kvp_buf, &recvlen, &requestid); + KASSERT(ret != ENOBUFS, ("hvkvp recvbuf is not large enough")); + /* XXX check recvlen to make sure that it contains enough data */ + hv_kvp_log_info("%s: read: context %p, ret =%d, recvlen=%d\n", __func__, context, ret, recvlen); } diff --git a/sys/dev/hyperv/utilities/hv_shutdown.c b/sys/dev/hyperv/utilities/hv_shutdown.c index 4cca5a6..49b2d87 100644 --- a/sys/dev/hyperv/utilities/hv_shutdown.c +++ b/sys/dev/hyperv/utilities/hv_shutdown.c @@ -67,8 +67,11 @@ hv_shutdown_cb(void *context) softc = (hv_util_sc*)context; buf = softc->receive_buffer;; channel = softc->channel; - ret = hv_vmbus_channel_recv_packet(channel, buf, PAGE_SIZE, - &recv_len, &request_id); + + recv_len = PAGE_SIZE; + ret = vmbus_chan_recv(channel, buf, &recv_len, &request_id); + KASSERT(ret != ENOBUFS, ("hvshutdown recvbuf is not large enough")); + /* XXX check recv_len to make sure that it contains enough data */ if ((ret == 0) && recv_len > 0) { diff --git a/sys/dev/hyperv/utilities/hv_timesync.c b/sys/dev/hyperv/utilities/hv_timesync.c index 1071cdd..e2e4321 100644 --- a/sys/dev/hyperv/utilities/hv_timesync.c +++ b/sys/dev/hyperv/utilities/hv_timesync.c @@ -144,8 +144,10 @@ hv_timesync_cb(void *context) channel = softc->util_sc.channel; time_buf = softc->util_sc.receive_buffer; - ret = hv_vmbus_channel_recv_packet(channel, time_buf, - PAGE_SIZE, &recvlen, &requestId); + recvlen = PAGE_SIZE; + ret = vmbus_chan_recv(channel, time_buf, &recvlen, &requestId); + KASSERT(ret != ENOBUFS, ("hvtimesync recvbuf is not large enough")); + /* XXX check recvlen to make sure that it contains enough data */ if ((ret == 0) && recvlen > 0) { icmsghdrp = (struct hv_vmbus_icmsg_hdr *) &time_buf[ diff --git a/sys/dev/hyperv/vmbus/hv_channel.c b/sys/dev/hyperv/vmbus/hv_channel.c index 9221de2..8397f22 100644 --- a/sys/dev/hyperv/vmbus/hv_channel.c +++ b/sys/dev/hyperv/vmbus/hv_channel.c @@ -736,84 +736,60 @@ vmbus_chan_send_prplist(struct hv_vmbus_channel *chan, return error; } -/** - * @brief Retrieve the user packet on the specified channel - */ int -hv_vmbus_channel_recv_packet( - hv_vmbus_channel* channel, - void* Buffer, - uint32_t buffer_len, - uint32_t* buffer_actual_len, - uint64_t* request_id) +vmbus_chan_recv(struct hv_vmbus_channel *chan, void *data, int *dlen0, + uint64_t *xactid) { - int ret; - uint32_t user_len; - uint32_t packet_len; - hv_vm_packet_descriptor desc; - - *buffer_actual_len = 0; - *request_id = 0; - - ret = hv_ring_buffer_peek(&channel->inbound, &desc, - sizeof(hv_vm_packet_descriptor)); - if (ret != 0) - return (0); + struct vmbus_chanpkt_hdr pkt; + int error, dlen, hlen; - packet_len = desc.length8 << 3; - user_len = packet_len - (desc.data_offset8 << 3); + error = hv_ring_buffer_peek(&chan->inbound, &pkt, sizeof(pkt)); + if (error) + return error; - *buffer_actual_len = user_len; + hlen = VMBUS_CHANPKT_GETLEN(pkt.cph_hlen); + dlen = VMBUS_CHANPKT_GETLEN(pkt.cph_tlen) - hlen; - if (user_len > buffer_len) - return (EINVAL); + if (*dlen0 < dlen) { + /* Return the size of this packet's data. */ + *dlen0 = dlen; + return ENOBUFS; + } - *request_id = desc.transaction_id; + *xactid = pkt.cph_xactid; + *dlen0 = dlen; - /* Copy over the packet to the user buffer */ - ret = hv_ring_buffer_read(&channel->inbound, Buffer, user_len, - (desc.data_offset8 << 3)); + /* Skip packet header */ + error = hv_ring_buffer_read(&chan->inbound, data, dlen, hlen); + KASSERT(!error, ("hv_ring_buffer_read failed")); - return (0); + return 0; } -/** - * @brief Retrieve the raw packet on the specified channel - */ int -hv_vmbus_channel_recv_packet_raw( - hv_vmbus_channel* channel, - void* buffer, - uint32_t buffer_len, - uint32_t* buffer_actual_len, - uint64_t* request_id) +vmbus_chan_recv_pkt(struct hv_vmbus_channel *chan, + struct vmbus_chanpkt_hdr *pkt0, int *pktlen0) { - int ret; - uint32_t packetLen; - hv_vm_packet_descriptor desc; - - *buffer_actual_len = 0; - *request_id = 0; - - ret = hv_ring_buffer_peek( - &channel->inbound, &desc, - sizeof(hv_vm_packet_descriptor)); - - if (ret != 0) - return (0); + struct vmbus_chanpkt_hdr pkt; + int error, pktlen; - packetLen = desc.length8 << 3; - *buffer_actual_len = packetLen; - - if (packetLen > buffer_len) - return (ENOBUFS); + error = hv_ring_buffer_peek(&chan->inbound, &pkt, sizeof(pkt)); + if (error) + return error; - *request_id = desc.transaction_id; + pktlen = VMBUS_CHANPKT_GETLEN(pkt.cph_tlen); + if (*pktlen0 < pktlen) { + /* Return the size of this packet. */ + *pktlen0 = pktlen; + return ENOBUFS; + } + *pktlen0 = pktlen; - /* Copy over the entire packet to the user buffer */ - ret = hv_ring_buffer_read(&channel->inbound, buffer, packetLen, 0); + /* Include packet header */ + error = hv_ring_buffer_read(&chan->inbound, pkt0, pktlen, 0); + KASSERT(!error, ("hv_ring_buffer_read failed")); - return (0); + return 0; } static void diff --git a/sys/dev/hyperv/vmbus/vmbus_reg.h b/sys/dev/hyperv/vmbus/vmbus_reg.h index b958652..8b64229 100644 --- a/sys/dev/hyperv/vmbus/vmbus_reg.h +++ b/sys/dev/hyperv/vmbus/vmbus_reg.h @@ -112,7 +112,6 @@ CTASSERT(sizeof(struct vmbus_mnf) == PAGE_SIZE); * Channel packets */ -#define VMBUS_CHANPKT_SIZE_SHIFT 3 #define VMBUS_CHANPKT_SIZE_ALIGN (1 << VMBUS_CHANPKT_SIZE_SHIFT) #define VMBUS_CHANPKT_SETLEN(pktlen, len) \ @@ -123,14 +122,6 @@ do { \ #define VMBUS_CHANPKT_TOTLEN(tlen) \ roundup2((tlen), VMBUS_CHANPKT_SIZE_ALIGN) -struct vmbus_chanpkt_hdr { - uint16_t cph_type; - uint16_t cph_hlen; /* header len, in 8 bytes */ - uint16_t cph_tlen; /* total len, in 8 bytes */ - uint16_t cph_flags; - uint64_t cph_xactid; -} __packed; - struct vmbus_chanpkt { struct vmbus_chanpkt_hdr cp_hdr; } __packed; |