All of lore.kernel.org
 help / color / mirror / Atom feed
From: Dexuan Cui <decui@microsoft.com>
To: gregkh@linuxfoundation.org, davem@davemloft.net,
	stephen@networkplumber.org, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	driverdev-devel@linuxdriverproject.org, olaf@aepfle.de,
	apw@canonical.com, jasowang@redhat.com, kys@microsoft.com,
	pebolle@tiscali.nl, stefanha@redhat.com
Subject: [PATCH V3 3/7] Drivers: hv: vmbus: add APIs to send/recv hvsock packet and get the r/w-ability
Date: Tue, 21 Jul 2015 03:58:13 -0700	[thread overview]
Message-ID: <1437476293-6837-1-git-send-email-decui@microsoft.com> (raw)

This will be used by the coming net/hvsock driver.

Signed-off-by: Dexuan Cui <decui@microsoft.com>
---
 drivers/hv/channel.c      | 133 ++++++++++++++++++++++++++++++++++++++++++++++
 drivers/hv/hyperv_vmbus.h |   4 ++
 drivers/hv/ring_buffer.c  |  14 +++++
 include/linux/hyperv.h    |  32 +++++++++++
 4 files changed, 183 insertions(+)

diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
index b09d1b7..ffdef03 100644
--- a/drivers/hv/channel.c
+++ b/drivers/hv/channel.c
@@ -758,6 +758,53 @@ int vmbus_sendpacket_pagebuffer_ctl(struct vmbus_channel *channel,
 EXPORT_SYMBOL_GPL(vmbus_sendpacket_pagebuffer_ctl);
 
 /*
+ * vmbus_sendpacket_hvsock - Send the hvsock payload 'buf' into the vmbus
+ * ringbuffer
+ */
+int vmbus_sendpacket_hvsock(struct vmbus_channel *channel, void *buf, u32 len)
+{
+	struct vmpipe_proto_header pipe_hdr;
+	struct vmpacket_descriptor desc;
+	struct kvec bufferlist[4];
+	u32 packetlen_aligned;
+	u32 packetlen;
+	u64 aligned_data = 0;
+	bool signal = false;
+	int ret;
+
+	packetlen = HVSOCK_HEADER_LEN + len;
+	packetlen_aligned = ALIGN(packetlen, sizeof(u64));
+
+	/* Setup the descriptor */
+	desc.type = VM_PKT_DATA_INBAND;
+	/* in 8-bytes granularity */
+	desc.offset8 = sizeof(struct vmpacket_descriptor) >> 3;
+	desc.len8 = (u16)(packetlen_aligned >> 3);
+	desc.flags = 0;
+	desc.trans_id = 0;
+
+	pipe_hdr.pkt_type = 1;
+	pipe_hdr.data_size = len;
+
+	bufferlist[0].iov_base = &desc;
+	bufferlist[0].iov_len  = sizeof(struct vmpacket_descriptor);
+	bufferlist[1].iov_base = &pipe_hdr;
+	bufferlist[1].iov_len  = sizeof(struct vmpipe_proto_header);
+	bufferlist[2].iov_base = buf;
+	bufferlist[2].iov_len  = len;
+	bufferlist[3].iov_base = &aligned_data;
+	bufferlist[3].iov_len  = packetlen_aligned - packetlen;
+
+	ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 4, &signal);
+
+	if (ret == 0 && signal)
+		vmbus_setevent(channel);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(vmbus_sendpacket_hvsock);
+
+/*
  * vmbus_sendpacket_pagebuffer - Send a range of single-page buffer
  * packets using a GPADL Direct packet type.
  */
@@ -978,3 +1025,89 @@ int vmbus_recvpacket_raw(struct vmbus_channel *channel, void *buffer,
 	return ret;
 }
 EXPORT_SYMBOL_GPL(vmbus_recvpacket_raw);
+
+/*
+ * vmbus_recvpacket_hvsock - Receive the hvsock payload from the vmbus
+ * ringbuffer into the 'buffer'.
+ */
+int vmbus_recvpacket_hvsock(struct vmbus_channel *channel, void *buffer,
+			    u32 bufferlen, u32 *buffer_actual_len)
+{
+	struct vmpipe_proto_header *pipe_hdr;
+	struct vmpacket_descriptor *desc;
+	u32 packet_len, payload_len;
+	bool signal = false;
+	int ret;
+
+	*buffer_actual_len = 0;
+
+	if (bufferlen < HVSOCK_HEADER_LEN)
+		return -ENOBUFS;
+
+	ret = hv_ringbuffer_peek(&channel->inbound, buffer,
+				 HVSOCK_HEADER_LEN);
+	if (ret != 0)
+		return 0;
+
+	desc = (struct vmpacket_descriptor *)buffer;
+	packet_len = desc->len8 << 3;
+	if (desc->type != VM_PKT_DATA_INBAND ||
+	    desc->offset8 != (sizeof(*desc) / 8) ||
+	    packet_len < HVSOCK_HEADER_LEN)
+		return -EIO;
+
+	pipe_hdr = (struct vmpipe_proto_header *)(desc + 1);
+	payload_len = pipe_hdr->data_size;
+
+	if (pipe_hdr->pkt_type != 1 || payload_len == 0)
+		return -EIO;
+
+	if (HVSOCK_PKT_LEN(payload_len) != packet_len + PREV_INDICES_LEN)
+		return -EIO;
+
+	if (bufferlen < packet_len - HVSOCK_HEADER_LEN)
+		return -ENOBUFS;
+
+	/* Copy over the hvsock payload to the user buffer */
+	ret = hv_ringbuffer_read(&channel->inbound, buffer,
+				 packet_len - HVSOCK_HEADER_LEN,
+				 HVSOCK_HEADER_LEN, &signal);
+	if (ret != 0)
+		return ret;
+
+	*buffer_actual_len = payload_len;
+
+	if (signal)
+		vmbus_setevent(channel);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(vmbus_recvpacket_hvsock);
+
+/*
+ * vmbus_get_hvsock_rw_status - can the ringbuffer be read/written?
+ */
+void vmbus_get_hvsock_rw_status(struct vmbus_channel *channel,
+				bool *can_read, bool *can_write)
+{
+	u32 avl_read_bytes, avl_write_bytes, dummy;
+
+	if (can_read != NULL) {
+		hv_get_ringbuffer_available_space(&channel->inbound,
+						  &avl_read_bytes,
+						  &dummy);
+		*can_read = avl_read_bytes >= HVSOCK_MIN_PKT_LEN;
+	}
+
+	/* We write into the ringbuffer only when we're able to write a
+	 * a payload of 4096 bytes (the actual written payload's length may be
+	 * less than 4096).
+	 */
+	if (can_write != NULL) {
+		hv_get_ringbuffer_available_space(&channel->outbound,
+						  &dummy,
+						  &avl_write_bytes);
+		*can_write = avl_write_bytes > HVSOCK_PKT_LEN(PAGE_SIZE);
+	}
+}
+EXPORT_SYMBOL_GPL(vmbus_get_hvsock_rw_status);
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
index cddc0c9..16b6ac4 100644
--- a/drivers/hv/hyperv_vmbus.h
+++ b/drivers/hv/hyperv_vmbus.h
@@ -608,6 +608,10 @@ int hv_ringbuffer_write(struct hv_ring_buffer_info *ring_info,
 int hv_ringbuffer_peek(struct hv_ring_buffer_info *ring_info, void *buffer,
 		   u32 buflen);
 
+void hv_get_ringbuffer_available_space(struct hv_ring_buffer_info *inring_info,
+				       u32 *bytes_avail_toread,
+				       u32 *bytes_avail_towrite);
+
 int hv_ringbuffer_read(struct hv_ring_buffer_info *ring_info,
 		   void *buffer,
 		   u32 buflen,
diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c
index 6361d12..e493c66 100644
--- a/drivers/hv/ring_buffer.c
+++ b/drivers/hv/ring_buffer.c
@@ -501,6 +501,20 @@ int hv_ringbuffer_peek(struct hv_ring_buffer_info *Inring_info,
 	return 0;
 }
 
+void hv_get_ringbuffer_available_space(struct hv_ring_buffer_info *inring_info,
+				       u32 *bytes_avail_toread,
+				       u32 *bytes_avail_towrite)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&inring_info->ring_lock, flags);
+
+	hv_get_ringbuffer_availbytes(inring_info,
+				     bytes_avail_toread,
+				     bytes_avail_towrite);
+
+	spin_unlock_irqrestore(&inring_info->ring_lock, flags);
+}
 
 /*
  *
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index 264093a..c8e27da 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -885,6 +885,9 @@ extern int vmbus_sendpacket_ctl(struct vmbus_channel *channel,
 				  u32 flags,
 				  bool kick_q);
 
+extern int vmbus_sendpacket_hvsock(struct vmbus_channel *channel,
+				   void *buf, u32 len);
+
 extern int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
 					    struct hv_page_buffer pagebuffers[],
 					    u32 pagecount,
@@ -934,6 +937,11 @@ extern int vmbus_recvpacket_raw(struct vmbus_channel *channel,
 				     u32 *buffer_actual_len,
 				     u64 *requestid);
 
+extern int vmbus_recvpacket_hvsock(struct vmbus_channel *channel, void *buffer,
+				   u32 bufferlen, u32 *buffer_actual_len);
+
+extern void vmbus_get_hvsock_rw_status(struct vmbus_channel *channel,
+				       bool *can_read, bool *can_write);
 
 extern void vmbus_ontimer(unsigned long data);
 
@@ -1261,4 +1269,28 @@ extern __u32 vmbus_proto_version;
 
 int vmbus_send_tl_connect_request(const uuid_le *shv_guest_servie_id,
 				  const uuid_le *shv_host_servie_id);
+struct vmpipe_proto_header {
+	u32 pkt_type;
+
+	union {
+		u32 data_size;
+		struct {
+			u16 data_size;
+			u16 offset;
+		} partial;
+	};
+} __packed;
+
+/* see hv_ringbuffer_read() and hv_ringbuffer_write() */
+#define PREV_INDICES_LEN	(sizeof(u64))
+
+#define HVSOCK_HEADER_LEN	(sizeof(struct vmpacket_descriptor) + \
+				 sizeof(struct vmpipe_proto_header))
+
+#define HVSOCK_PKT_LEN(payload_len)	(HVSOCK_HEADER_LEN + \
+					ALIGN((payload_len), 8) + \
+					PREV_INDICES_LEN)
+
+#define HVSOCK_MIN_PKT_LEN	HVSOCK_PKT_LEN(1)
+
 #endif /* _HYPERV_H */
-- 
2.1.0


             reply	other threads:[~2015-07-21  9:33 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-07-21 10:58 Dexuan Cui [this message]
2015-07-21 14:07 ` [PATCH V3 3/7] Drivers: hv: vmbus: add APIs to send/recv hvsock packet and get the r/w-ability Vitaly Kuznetsov
2015-07-22 10:09   ` Dexuan Cui
2015-07-22 10:09     ` Dexuan Cui
2015-07-22 10:35     ` Dan Carpenter
2015-07-22 10:35       ` Dan Carpenter
2015-07-23  3:05       ` Dexuan Cui
2015-07-23  3:05         ` Dexuan Cui
2015-07-23 10:10         ` Dan Carpenter
2015-07-23 10:10           ` Dan Carpenter
2015-07-23 10:24           ` Dan Carpenter
2015-07-23 11:05             ` Dexuan Cui
2015-07-24  6:27             ` Sudip Mukherjee
2015-07-24  8:33               ` Dan Carpenter
2015-07-24  8:33                 ` Dan Carpenter

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1437476293-6837-1-git-send-email-decui@microsoft.com \
    --to=decui@microsoft.com \
    --cc=apw@canonical.com \
    --cc=davem@davemloft.net \
    --cc=driverdev-devel@linuxdriverproject.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=jasowang@redhat.com \
    --cc=kys@microsoft.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=olaf@aepfle.de \
    --cc=pebolle@tiscali.nl \
    --cc=stefanha@redhat.com \
    --cc=stephen@networkplumber.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.