These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / hv / channel.c
index 54da66d..9098f13 100644 (file)
@@ -73,6 +73,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
        unsigned long flags;
        int ret, err = 0;
        unsigned long t;
+       struct page *page;
 
        spin_lock_irqsave(&newchannel->lock, flags);
        if (newchannel->state == CHANNEL_OPEN_STATE) {
@@ -87,8 +88,17 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
        newchannel->channel_callback_context = context;
 
        /* Allocate the ring buffer */
-       out = (void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO,
-               get_order(send_ringbuffer_size + recv_ringbuffer_size));
+       page = alloc_pages_node(cpu_to_node(newchannel->target_cpu),
+                               GFP_KERNEL|__GFP_ZERO,
+                               get_order(send_ringbuffer_size +
+                               recv_ringbuffer_size));
+
+       if (!page)
+               out = (void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO,
+                                              get_order(send_ringbuffer_size +
+                                              recv_ringbuffer_size));
+       else
+               out = (void *)page_address(page);
 
        if (!out) {
                err = -ENOMEM;
@@ -178,19 +188,18 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
                goto error1;
        }
 
-
-       if (open_info->response.open_result.status)
-               err = open_info->response.open_result.status;
-
        spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
        list_del(&open_info->msglistentry);
        spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
 
-       if (err == 0)
-               newchannel->state = CHANNEL_OPENED_STATE;
+       if (open_info->response.open_result.status) {
+               err = -EAGAIN;
+               goto error_gpadl;
+       }
 
+       newchannel->state = CHANNEL_OPENED_STATE;
        kfree(open_info);
-       return err;
+       return 0;
 
 error1:
        spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
@@ -592,6 +601,7 @@ int vmbus_sendpacket_ctl(struct vmbus_channel *channel, void *buffer,
        u64 aligned_data = 0;
        int ret;
        bool signal = false;
+       int num_vecs = ((bufferlen != 0) ? 3 : 1);
 
 
        /* Setup the descriptor */
@@ -609,7 +619,8 @@ int vmbus_sendpacket_ctl(struct vmbus_channel *channel, void *buffer,
        bufferlist[2].iov_base = &aligned_data;
        bufferlist[2].iov_len = (packetlen_aligned - packetlen);
 
-       ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3, &signal);
+       ret = hv_ringbuffer_write(&channel->outbound, bufferlist, num_vecs,
+                                 &signal);
 
        /*
         * Signalling the host is conditional on many factors:
@@ -619,10 +630,19 @@ int vmbus_sendpacket_ctl(struct vmbus_channel *channel, void *buffer,
         *    on the ring. We will not signal if more data is
         *    to be placed.
         *
+        * Based on the channel signal state, we will decide
+        * which signaling policy will be applied.
+        *
         * If we cannot write to the ring-buffer; signal the host
         * even if we may not have written anything. This is a rare
         * enough condition that it should not matter.
         */
+
+       if (channel->signal_policy)
+               signal = true;
+       else
+               kick_q = true;
+
        if (((ret == 0) && kick_q && signal) || (ret))
                vmbus_setevent(channel);
 
@@ -722,10 +742,19 @@ int vmbus_sendpacket_pagebuffer_ctl(struct vmbus_channel *channel,
         *    on the ring. We will not signal if more data is
         *    to be placed.
         *
+        * Based on the channel signal state, we will decide
+        * which signaling policy will be applied.
+        *
         * If we cannot write to the ring-buffer; signal the host
         * even if we may not have written anything. This is a rare
         * enough condition that it should not matter.
         */
+
+       if (channel->signal_policy)
+               signal = true;
+       else
+               kick_q = true;
+
        if (((ret == 0) && kick_q && signal) || (ret))
                vmbus_setevent(channel);