Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1363779 > unrolled thread

[PATCH 1/7] Drivers: hv: vmbus: Introduce functions for estimating room in the ring buffer

Started by"K. Y. Srinivasan" <kys@microsoft.com>
First post2016-03-24 00:20 +0100
Last post2016-03-24 00:20 +0100
Articles 9 — 3 participants

Back to article view | Back to linux.kernel

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  [PATCH 1/7] Drivers: hv: vmbus: Introduce functions for estimating room in the ring buffer "K. Y. Srinivasan" <kys@microsoft.com> - 2016-03-24 00:20 +0100
    [PATCH 5/7] Drivers: hv: vmbus: Export the vmbus_set_event() API "K. Y. Srinivasan" <kys@microsoft.com> - 2016-03-24 00:20 +0100
    [PATCH 6/7] Drivers: hv: vmbus: Move some ring buffer functions to hyperv.h "K. Y. Srinivasan" <kys@microsoft.com> - 2016-03-24 00:20 +0100
    [PATCH 3/7] Drivers: hv: vmbus: Fix a bug in hv_need_to_signal_on_read() "K. Y. Srinivasan" <kys@microsoft.com> - 2016-03-24 00:20 +0100
      Re: [PATCH 3/7] Drivers: hv: vmbus: Fix a bug in  hv_need_to_signal_on_read() Greg KH <gregkh@linuxfoundation.org> - 2016-04-01 02:00 +0200
        RE: [PATCH 3/7] Drivers: hv: vmbus: Fix a bug in  hv_need_to_signal_on_read() KY Srinivasan <kys@microsoft.com> - 2016-04-01 23:10 +0200
      Re: [PATCH 3/7] Drivers: hv: vmbus: Fix a bug in  hv_need_to_signal_on_read() Greg KH <gregkh@linuxfoundation.org> - 2016-04-01 02:10 +0200
        RE: [PATCH 3/7] Drivers: hv: vmbus: Fix a bug in  hv_need_to_signal_on_read() KY Srinivasan <kys@microsoft.com> - 2016-04-02 00:00 +0200
    [PATCH 7/7] Drivers: hv: vmbus: Implement APIs to support "in place" consumption of vmbus packets "K. Y. Srinivasan" <kys@microsoft.com> - 2016-03-24 00:20 +0100

#1363779 — [PATCH 1/7] Drivers: hv: vmbus: Introduce functions for estimating room in the ring buffer

From"K. Y. Srinivasan" <kys@microsoft.com>
Date2016-03-24 00:20 +0100
Subject[PATCH 1/7] Drivers: hv: vmbus: Introduce functions for estimating room in the ring buffer
Message-ID<rg0ee-2bF-5@gated-at.bofh.it>
Introduce separate functions for estimating how much can be read from
and written to the ring buffer.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
---
 drivers/hv/ring_buffer.c |   24 ++++--------------------
 include/linux/hyperv.h   |   27 +++++++++++++++++++++++++++
 2 files changed, 31 insertions(+), 20 deletions(-)

diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c
index 085003a..902375b 100644
--- a/drivers/hv/ring_buffer.c
+++ b/drivers/hv/ring_buffer.c
@@ -38,8 +38,6 @@ void hv_begin_read(struct hv_ring_buffer_info *rbi)
 
 u32 hv_end_read(struct hv_ring_buffer_info *rbi)
 {
-	u32 read;
-	u32 write;
 
 	rbi->ring_buffer->interrupt_mask = 0;
 	mb();
@@ -49,9 +47,7 @@ u32 hv_end_read(struct hv_ring_buffer_info *rbi)
 	 * If it is not, we raced and we need to process new
 	 * incoming messages.
 	 */
-	hv_get_ringbuffer_availbytes(rbi, &read, &write);
-
-	return read;
+	return hv_get_bytes_to_read(rbi);
 }
 
 /*
@@ -106,18 +102,13 @@ static bool hv_need_to_signal(u32 old_write, struct hv_ring_buffer_info *rbi)
 static bool hv_need_to_signal_on_read(struct hv_ring_buffer_info *rbi)
 {
 	u32 cur_write_sz;
-	u32 r_size;
-	u32 write_loc = rbi->ring_buffer->write_index;
-	u32 read_loc = rbi->ring_buffer->read_index;
 	u32 pending_sz = rbi->ring_buffer->pending_send_sz;
 
 	/* If the other end is not blocked on write don't bother. */
 	if (pending_sz == 0)
 		return false;
 
-	r_size = rbi->ring_datasize;
-	cur_write_sz = write_loc >= read_loc ? r_size - (write_loc - read_loc) :
-			read_loc - write_loc;
+	cur_write_sz = hv_get_bytes_to_write(rbi);
 
 	if (cur_write_sz >= pending_sz)
 		return true;
@@ -317,7 +308,6 @@ int hv_ringbuffer_write(struct hv_ring_buffer_info *outring_info,
 {
 	int i = 0;
 	u32 bytes_avail_towrite;
-	u32 bytes_avail_toread;
 	u32 totalbytes_towrite = 0;
 
 	u32 next_write_location;
@@ -333,9 +323,7 @@ int hv_ringbuffer_write(struct hv_ring_buffer_info *outring_info,
 	if (lock)
 		spin_lock_irqsave(&outring_info->ring_lock, flags);
 
-	hv_get_ringbuffer_availbytes(outring_info,
-				&bytes_avail_toread,
-				&bytes_avail_towrite);
+	bytes_avail_towrite = hv_get_bytes_to_write(outring_info);
 
 	/*
 	 * If there is only room for the packet, assume it is full.
@@ -386,7 +374,6 @@ int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info,
 		       void *buffer, u32 buflen, u32 *buffer_actual_len,
 		       u64 *requestid, bool *signal, bool raw)
 {
-	u32 bytes_avail_towrite;
 	u32 bytes_avail_toread;
 	u32 next_read_location = 0;
 	u64 prev_indices = 0;
@@ -402,10 +389,7 @@ int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info,
 	*buffer_actual_len = 0;
 	*requestid = 0;
 
-	hv_get_ringbuffer_availbytes(inring_info,
-				&bytes_avail_toread,
-				&bytes_avail_towrite);
-
+	bytes_avail_toread = hv_get_bytes_to_read(inring_info);
 	/* Make sure there is something to read */
 	if (bytes_avail_toread < sizeof(desc)) {
 		/*
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index ecd81c3..a6b053c 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -151,6 +151,33 @@ hv_get_ringbuffer_availbytes(struct hv_ring_buffer_info *rbi,
 	*read = dsize - *write;
 }
 
+static inline u32 hv_get_bytes_to_read(struct hv_ring_buffer_info *rbi)
+{
+	u32 read_loc, write_loc, dsize, read;
+
+	dsize = rbi->ring_datasize;
+	read_loc = rbi->ring_buffer->read_index;
+	write_loc = READ_ONCE(rbi->ring_buffer->write_index);
+
+	read = write_loc >= read_loc ? (write_loc - read_loc) :
+		(dsize - read_loc) + write_loc;
+
+	return read;
+}
+
+static inline u32 hv_get_bytes_to_write(struct hv_ring_buffer_info *rbi)
+{
+	u32 read_loc, write_loc, dsize, write;
+
+	dsize = rbi->ring_datasize;
+	read_loc = READ_ONCE(rbi->ring_buffer->read_index);
+	write_loc = rbi->ring_buffer->write_index;
+
+	write = write_loc >= read_loc ? dsize - (write_loc - read_loc) :
+		read_loc - write_loc;
+	return write;
+}
+
 /*
  * VMBUS version is 32 bit entity broken up into
  * two 16 bit quantities: major_number. minor_number.
-- 
1.7.4.1

[toc] | [next] | [standalone]


#1363780 — [PATCH 5/7] Drivers: hv: vmbus: Export the vmbus_set_event() API

From"K. Y. Srinivasan" <kys@microsoft.com>
Date2016-03-24 00:20 +0100
Subject[PATCH 5/7] Drivers: hv: vmbus: Export the vmbus_set_event() API
Message-ID<rg0ee-2bF-9@gated-at.bofh.it>
In reply to#1363779
In preparation for moving some ring buffer functionality out of the
vmbus driver, export the API for signaling the host.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
---
 drivers/hv/connection.c   |    1 +
 drivers/hv/hyperv_vmbus.h |    2 --
 include/linux/hyperv.h    |    1 +
 3 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c
index d02f137..fcf8a02 100644
--- a/drivers/hv/connection.c
+++ b/drivers/hv/connection.c
@@ -495,3 +495,4 @@ void vmbus_set_event(struct vmbus_channel *channel)
 
 	hv_do_hypercall(HVCALL_SIGNAL_EVENT, channel->sig_event, NULL);
 }
+EXPORT_SYMBOL_GPL(vmbus_set_event);
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
index 28e9df9..8cbd630 100644
--- a/drivers/hv/hyperv_vmbus.h
+++ b/drivers/hv/hyperv_vmbus.h
@@ -678,8 +678,6 @@ void vmbus_disconnect(void);
 
 int vmbus_post_msg(void *buffer, size_t buflen);
 
-void vmbus_set_event(struct vmbus_channel *channel);
-
 void vmbus_on_event(unsigned long data);
 void vmbus_on_msg_dpc(unsigned long data);
 
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index a6b053c..4adeb6e 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -1365,4 +1365,5 @@ 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);
+void vmbus_set_event(struct vmbus_channel *channel);
 #endif /* _HYPERV_H */
-- 
1.7.4.1

[toc] | [prev] | [next] | [standalone]


#1363781 — [PATCH 6/7] Drivers: hv: vmbus: Move some ring buffer functions to hyperv.h

From"K. Y. Srinivasan" <kys@microsoft.com>
Date2016-03-24 00:20 +0100
Subject[PATCH 6/7] Drivers: hv: vmbus: Move some ring buffer functions to hyperv.h
Message-ID<rg0ee-2bF-11@gated-at.bofh.it>
In reply to#1363779
In preparation for implementing APIs for in-place consumption of VMBUS
packets, movve some ring buffer functionality into hyperv.h

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
---
 drivers/hv/ring_buffer.c |   42 ------------------------------------------
 include/linux/hyperv.h   |   42 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 42 insertions(+), 42 deletions(-)

diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c
index c2c2b2e..253311b 100644
--- a/drivers/hv/ring_buffer.c
+++ b/drivers/hv/ring_buffer.c
@@ -84,40 +84,6 @@ static bool hv_need_to_signal(u32 old_write, struct hv_ring_buffer_info *rbi)
 	return false;
 }
 
-/*
- * To optimize the flow management on the send-side,
- * when the sender is blocked because of lack of
- * sufficient space in the ring buffer, potential the
- * consumer of the ring buffer can signal the producer.
- * This is controlled by the following parameters:
- *
- * 1. pending_send_sz: This is the size in bytes that the
- *    producer is trying to send.
- * 2. The feature bit feat_pending_send_sz set to indicate if
- *    the consumer of the ring will signal when the ring
- *    state transitions from being full to a state where
- *    there is room for the producer to send the pending packet.
- */
-
-static bool hv_need_to_signal_on_read(struct hv_ring_buffer_info *rbi)
-{
-	u32 cur_write_sz;
-	u32 pending_sz;
-
-	virt_mb();
-	pending_sz = READ_ONCE(rbi->ring_buffer->pending_send_sz);
-	/* If the other end is not blocked on write don't bother. */
-	if (pending_sz == 0)
-		return false;
-
-	cur_write_sz = hv_get_bytes_to_write(rbi);
-
-	if (cur_write_sz >= pending_sz)
-		return true;
-
-	return false;
-}
-
 /* Get the next write location for the specified ring buffer. */
 static inline u32
 hv_get_next_write_location(struct hv_ring_buffer_info *ring_info)
@@ -169,14 +135,6 @@ hv_set_next_read_location(struct hv_ring_buffer_info *ring_info,
 }
 
 
-/* Get the start of the ring buffer. */
-static inline void *
-hv_get_ring_buffer(struct hv_ring_buffer_info *ring_info)
-{
-	return (void *)ring_info->ring_buffer->buffer;
-}
-
-
 /* Get the size of the ring buffer. */
 static inline u32
 hv_get_ring_buffersize(struct hv_ring_buffer_info *ring_info)
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index 4adeb6e..8fc9b09 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -1366,4 +1366,46 @@ 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);
 void vmbus_set_event(struct vmbus_channel *channel);
+
+/* Get the start of the ring buffer. */
+static inline void *
+hv_get_ring_buffer(struct hv_ring_buffer_info *ring_info)
+{
+	return (void *)ring_info->ring_buffer->buffer;
+}
+
+/*
+ * To optimize the flow management on the send-side,
+ * when the sender is blocked because of lack of
+ * sufficient space in the ring buffer, potential the
+ * consumer of the ring buffer can signal the producer.
+ * This is controlled by the following parameters:
+ *
+ * 1. pending_send_sz: This is the size in bytes that the
+ *    producer is trying to send.
+ * 2. The feature bit feat_pending_send_sz set to indicate if
+ *    the consumer of the ring will signal when the ring
+ *    state transitions from being full to a state where
+ *    there is room for the producer to send the pending packet.
+ */
+
+static inline  bool hv_need_to_signal_on_read(struct hv_ring_buffer_info *rbi)
+{
+	u32 cur_write_sz;
+	u32 pending_sz;
+
+	virt_mb();
+	pending_sz = READ_ONCE(rbi->ring_buffer->pending_send_sz);
+	/* If the other end is not blocked on write don't bother. */
+	if (pending_sz == 0)
+		return false;
+
+	cur_write_sz = hv_get_bytes_to_write(rbi);
+
+	if (cur_write_sz >= pending_sz)
+		return true;
+
+	return false;
+}
+
 #endif /* _HYPERV_H */
-- 
1.7.4.1

[toc] | [prev] | [next] | [standalone]


#1363782 — [PATCH 3/7] Drivers: hv: vmbus: Fix a bug in hv_need_to_signal_on_read()

From"K. Y. Srinivasan" <kys@microsoft.com>
Date2016-03-24 00:20 +0100
Subject[PATCH 3/7] Drivers: hv: vmbus: Fix a bug in hv_need_to_signal_on_read()
Message-ID<rg0ee-2bF-13@gated-at.bofh.it>
In reply to#1363779
We need to issue a full memory barrier prior making a signalling decision.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Cc: stable@vger.kernel.org
---
 drivers/hv/ring_buffer.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c
index 2919395..67dc245 100644
--- a/drivers/hv/ring_buffer.c
+++ b/drivers/hv/ring_buffer.c
@@ -104,6 +104,7 @@ static bool hv_need_to_signal_on_read(struct hv_ring_buffer_info *rbi)
 	u32 cur_write_sz;
 	u32 pending_sz;
 
+	mb();
 	pending_sz = READ_ONCE(rbi->ring_buffer->pending_send_sz);
 	/* If the other end is not blocked on write don't bother. */
 	if (pending_sz == 0)
-- 
1.7.4.1

[toc] | [prev] | [next] | [standalone]


#1368890 — Re: [PATCH 3/7] Drivers: hv: vmbus: Fix a bug in hv_need_to_signal_on_read()

FromGreg KH <gregkh@linuxfoundation.org>
Date2016-04-01 02:00 +0200
SubjectRe: [PATCH 3/7] Drivers: hv: vmbus: Fix a bug in hv_need_to_signal_on_read()
Message-ID<riUFj-42N-1@gated-at.bofh.it>
In reply to#1363782
On Wed, Mar 23, 2016 at 05:53:53PM -0700, K. Y. Srinivasan wrote:
> We need to issue a full memory barrier prior making a signalling decision.
> 
> Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
> Cc: stable@vger.kernel.org
> ---
>  drivers/hv/ring_buffer.c |    1 +
>  1 files changed, 1 insertions(+), 0 deletions(-)

why is this burried in a 7 patch series?  Don't you want this in
4.6-final?

Please break this out into a separate patch, and redo this series.

thanks,

greg k-h

[toc] | [prev] | [next] | [standalone]


#1369592 — RE: [PATCH 3/7] Drivers: hv: vmbus: Fix a bug in hv_need_to_signal_on_read()

FromKY Srinivasan <kys@microsoft.com>
Date2016-04-01 23:10 +0200
SubjectRE: [PATCH 3/7] Drivers: hv: vmbus: Fix a bug in hv_need_to_signal_on_read()
Message-ID<rjeum-1Et-5@gated-at.bofh.it>
In reply to#1368890

> -----Original Message-----
> From: Greg KH [mailto:gregkh@linuxfoundation.org]
> Sent: Thursday, March 31, 2016 5:00 PM
> To: KY Srinivasan <kys@microsoft.com>
> Cc: linux-kernel@vger.kernel.org; devel@linuxdriverproject.org;
> olaf@aepfle.de; apw@canonical.com; vkuznets@redhat.com;
> jasowang@redhat.com; stable@vger.kernel.org
> Subject: Re: [PATCH 3/7] Drivers: hv: vmbus: Fix a bug in
> hv_need_to_signal_on_read()
> 
> On Wed, Mar 23, 2016 at 05:53:53PM -0700, K. Y. Srinivasan wrote:
> > We need to issue a full memory barrier prior making a signalling decision.
> >
> > Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
> > Cc: stable@vger.kernel.org
> > ---
> >  drivers/hv/ring_buffer.c |    1 +
> >  1 files changed, 1 insertions(+), 0 deletions(-)
> 
> why is this burried in a 7 patch series?  Don't you want this in
> 4.6-final?
> 
> Please break this out into a separate patch, and redo this series.

Will do.

Thanks,

K. Y
> 
> thanks,
> 
> greg k-h

[toc] | [prev] | [next] | [standalone]


#1368892 — Re: [PATCH 3/7] Drivers: hv: vmbus: Fix a bug in hv_need_to_signal_on_read()

FromGreg KH <gregkh@linuxfoundation.org>
Date2016-04-01 02:10 +0200
SubjectRe: [PATCH 3/7] Drivers: hv: vmbus: Fix a bug in hv_need_to_signal_on_read()
Message-ID<riUP0-4r5-3@gated-at.bofh.it>
In reply to#1363782
On Wed, Mar 23, 2016 at 05:53:53PM -0700, K. Y. Srinivasan wrote:
> We need to issue a full memory barrier prior making a signalling decision.
> 
> Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
> Cc: stable@vger.kernel.org
> ---
>  drivers/hv/ring_buffer.c |    1 +
>  1 files changed, 1 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c
> index 2919395..67dc245 100644
> --- a/drivers/hv/ring_buffer.c
> +++ b/drivers/hv/ring_buffer.c
> @@ -104,6 +104,7 @@ static bool hv_need_to_signal_on_read(struct hv_ring_buffer_info *rbi)
>  	u32 cur_write_sz;
>  	u32 pending_sz;
>  
> +	mb();

And, are you sure this is correct?  You better document the heck out of
this, why it's here, and what it is protecting.  "raw" mb() calls are
really rare for good reason.

thanks,

greg k-h

[toc] | [prev] | [next] | [standalone]


#1369614 — RE: [PATCH 3/7] Drivers: hv: vmbus: Fix a bug in hv_need_to_signal_on_read()

FromKY Srinivasan <kys@microsoft.com>
Date2016-04-02 00:00 +0200
SubjectRE: [PATCH 3/7] Drivers: hv: vmbus: Fix a bug in hv_need_to_signal_on_read()
Message-ID<rjfgJ-1XC-1@gated-at.bofh.it>
In reply to#1368892

> -----Original Message-----
> From: Greg KH [mailto:gregkh@linuxfoundation.org]
> Sent: Thursday, March 31, 2016 5:00 PM
> To: KY Srinivasan <kys@microsoft.com>
> Cc: linux-kernel@vger.kernel.org; devel@linuxdriverproject.org;
> olaf@aepfle.de; apw@canonical.com; vkuznets@redhat.com;
> jasowang@redhat.com; stable@vger.kernel.org
> Subject: Re: [PATCH 3/7] Drivers: hv: vmbus: Fix a bug in
> hv_need_to_signal_on_read()
> 
> On Wed, Mar 23, 2016 at 05:53:53PM -0700, K. Y. Srinivasan wrote:
> > We need to issue a full memory barrier prior making a signalling decision.
> >
> > Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
> > Cc: stable@vger.kernel.org
> > ---
> >  drivers/hv/ring_buffer.c |    1 +
> >  1 files changed, 1 insertions(+), 0 deletions(-)
> >
> > diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c
> > index 2919395..67dc245 100644
> > --- a/drivers/hv/ring_buffer.c
> > +++ b/drivers/hv/ring_buffer.c
> > @@ -104,6 +104,7 @@ static bool hv_need_to_signal_on_read(struct
> hv_ring_buffer_info *rbi)
> >  	u32 cur_write_sz;
> >  	u32 pending_sz;
> >
> > +	mb();
> 
> And, are you sure this is correct?  You better document the heck out of
> this, why it's here, and what it is protecting.  "raw" mb() calls are
> really rare for good reason.

Yes; I am sure I need this barrier. This is a lockless ringbuffer code where
the reader  updates the read index while the writer only updates the
write index and they each sample the index modified by the other end to
make decisions.  Here is the reason for having this barrier:

"If the reading of the pend_sz (in the function hv_need_to_signal_on_read)
were to be reordered and read before we commit the new read index we could 
have a problem. If the host were to set the pending_sz after we have sampled pending_sz
and go to sleep before we commit the read index, we could miss sending the interrupt."

I will add the necessary documentation here.

Regards,

K. Y 

[toc] | [prev] | [next] | [standalone]


#1363783 — [PATCH 7/7] Drivers: hv: vmbus: Implement APIs to support "in place" consumption of vmbus packets

From"K. Y. Srinivasan" <kys@microsoft.com>
Date2016-03-24 00:20 +0100
Subject[PATCH 7/7] Drivers: hv: vmbus: Implement APIs to support "in place" consumption of vmbus packets
Message-ID<rg0ef-2bF-21@gated-at.bofh.it>
In reply to#1363779
Implement APIs for in-place consumption of vmbus packets. Currently, each
packet is copied and processed one at a time and as part of processing
each packet we potentially may signal the host (if it is waiting for
room to produce a packet).

These APIs help batched in-place processing of vmbus packets.
We also optimize host signaling by having a separate API to signal
the end of in-place consumption. With netvsc using these APIs,
on an iperf run on average I see about 20X reduction in checks to
signal the host.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
---
 drivers/hv/ring_buffer.c |    1 +
 include/linux/hyperv.h   |   86 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 87 insertions(+), 0 deletions(-)

diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c
index 253311b..a2a38ab 100644
--- a/drivers/hv/ring_buffer.c
+++ b/drivers/hv/ring_buffer.c
@@ -132,6 +132,7 @@ hv_set_next_read_location(struct hv_ring_buffer_info *ring_info,
 		    u32 next_read_location)
 {
 	ring_info->ring_buffer->read_index = next_read_location;
+	ring_info->priv_read_index = next_read_location;
 }
 
 
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index 8fc9b09..3fadbaf 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -126,6 +126,8 @@ struct hv_ring_buffer_info {
 
 	u32 ring_datasize;		/* < ring_size */
 	u32 ring_data_startoffset;
+	u32 priv_write_index;
+	u32 priv_read_index;
 };
 
 /*
@@ -1408,4 +1410,88 @@ static inline  bool hv_need_to_signal_on_read(struct hv_ring_buffer_info *rbi)
 	return false;
 }
 
+/*
+ * An API to support in-place processing of incoming VMBUS packets.
+ */
+#define VMBUS_PKT_TRAILER	8
+
+static inline struct vmpacket_descriptor *
+get_next_pkt_raw(struct vmbus_channel *channel)
+{
+	struct hv_ring_buffer_info *ring_info = &channel->inbound;
+	u32 read_loc = ring_info->priv_read_index;
+	void *ring_buffer = hv_get_ring_buffer(ring_info);
+	struct vmpacket_descriptor *cur_desc;
+	u32 packetlen;
+	u32 dsize = ring_info->ring_datasize;
+	u32 delta = read_loc - ring_info->ring_buffer->read_index;
+	u32 bytes_avail_toread = (hv_get_bytes_to_read(ring_info) - delta);
+
+	if (bytes_avail_toread < sizeof(struct vmpacket_descriptor))
+		return NULL;
+
+	if ((read_loc + sizeof(*cur_desc)) > dsize)
+		return NULL;
+
+	cur_desc = ring_buffer + read_loc;
+	packetlen = cur_desc->len8 << 3;
+
+	/*
+	 * If the packet under consideration is wrapping around,
+	 * return failure.
+	 */
+	if ((read_loc + packetlen + VMBUS_PKT_TRAILER) > (dsize - 1))
+		return NULL;
+
+	return cur_desc;
+}
+
+/*
+ * A helper function to step through packets "in-place"
+ * This API is to be called after each successful call
+ * get_next_pkt_raw().
+ */
+static inline void put_pkt_raw(struct vmbus_channel *channel,
+				struct vmpacket_descriptor *desc)
+{
+	struct hv_ring_buffer_info *ring_info = &channel->inbound;
+	u32 read_loc = ring_info->priv_read_index;
+	u32 packetlen = desc->len8 << 3;
+	u32 dsize = ring_info->ring_datasize;
+
+	if ((read_loc + packetlen + VMBUS_PKT_TRAILER) > dsize)
+		BUG();
+	/*
+	 * Include the packet trailer.
+	 */
+	ring_info->priv_read_index += packetlen + VMBUS_PKT_TRAILER;
+}
+
+/*
+ * This call commits the read index and potentially signals the host.
+ * Here is the pattern for using the "in-place" consumption APIs:
+ *
+ * while (get_next_pkt_raw() {
+ *	process the packet "in-place";
+ *	put_pkt_raw();
+ * }
+ * if (packets processed in place)
+ *	commit_rd_index();
+ */
+static inline void commit_rd_index(struct vmbus_channel *channel)
+{
+	struct hv_ring_buffer_info *ring_info = &channel->inbound;
+	/*
+	 * Make sure all reads are done before we update the read index since
+	 * the writer may start writing to the read area once the read index
+	 * is updated.
+	 */
+	virt_rmb();
+	ring_info->ring_buffer->read_index = ring_info->priv_read_index;
+
+	if (hv_need_to_signal_on_read(ring_info))
+		vmbus_set_event(channel);
+}
+
+
 #endif /* _HYPERV_H */
-- 
1.7.4.1

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web