Drivers: hv: Optimize signaling in the read path
K. Y. Srinivasan [Sat, 1 Dec 2012 14:46:35 +0000 (06:46 -0800)]
Now that we have the infratructure for correctly determining when we
should signal the host; optimize the signaling on the read side -
signaling the guest from the host.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

drivers/hv/connection.c

index 650c9f0..d1019a7 100644 (file)
@@ -212,6 +212,9 @@ static void process_chn_event(u32 relid)
 {
        struct vmbus_channel *channel;
        unsigned long flags;
+       void *arg;
+       bool read_state;
+       u32 bytes_to_read;
 
        /*
         * Find the channel based on this relid and invokes the
@@ -234,10 +237,29 @@ static void process_chn_event(u32 relid)
         */
 
        spin_lock_irqsave(&channel->inbound_lock, flags);
-       if (channel->onchannel_callback != NULL)
-               channel->onchannel_callback(channel->channel_callback_context);
-       else
+       if (channel->onchannel_callback != NULL) {
+               arg = channel->channel_callback_context;
+               read_state = channel->batched_reading;
+               /*
+                * This callback reads the messages sent by the host.
+                * We can optimize host to guest signaling by ensuring:
+                * 1. While reading the channel, we disable interrupts from
+                *    host.
+                * 2. Ensure that we process all posted messages from the host
+                *    before returning from this callback.
+                * 3. Once we return, enable signaling from the host. Once this
+                *    state is set we check to see if additional packets are
+                *    available to read. In this case we repeat the process.
+                */
+
+               do {
+                       hv_begin_read(&channel->inbound);
+                       channel->onchannel_callback(arg);
+                       bytes_to_read = hv_end_read(&channel->inbound);
+               } while (read_state && (bytes_to_read != 0));
+       } else {
                pr_err("no channel callback for relid - %u\n", relid);
+       }
 
        spin_unlock_irqrestore(&channel->inbound_lock, flags);
 }