Merge branch 'linux-linaro-lsk' into linux-linaro-lsk-android
[firefly-linux-kernel-4.4.55.git] / drivers / hv / hv_balloon.c
index deb5c25305aff4622ceb8f84a1598902e484a6ce..694173f662d1bec6be3eecf492907bdf216575e3 100644 (file)
@@ -19,6 +19,7 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/kernel.h>
+#include <linux/jiffies.h>
 #include <linux/mman.h>
 #include <linux/delay.h>
 #include <linux/init.h>
@@ -459,6 +460,11 @@ static bool do_hot_add;
  */
 static uint pressure_report_delay = 45;
 
+/*
+ * The last time we posted a pressure report to host.
+ */
+static unsigned long last_post_time;
+
 module_param(hot_add, bool, (S_IRUGO | S_IWUSR));
 MODULE_PARM_DESC(hot_add, "If set attempt memory hot_add");
 
@@ -542,6 +548,7 @@ struct hv_dynmem_device {
 
 static struct hv_dynmem_device dm_device;
 
+static void post_status(struct hv_dynmem_device *dm);
 #ifdef CONFIG_MEMORY_HOTPLUG
 
 static void hv_bring_pgs_online(unsigned long start_pfn, unsigned long size)
@@ -612,7 +619,7 @@ static void hv_mem_hot_add(unsigned long start, unsigned long size,
                 * have not been "onlined" within the allowed time.
                 */
                wait_for_completion_timeout(&dm_device.ol_waitevent, 5*HZ);
-
+               post_status(&dm_device);
        }
 
        return;
@@ -951,11 +958,17 @@ static void post_status(struct hv_dynmem_device *dm)
 {
        struct dm_status status;
        struct sysinfo val;
+       unsigned long now = jiffies;
+       unsigned long last_post = last_post_time;
 
        if (pressure_report_delay > 0) {
                --pressure_report_delay;
                return;
        }
+
+       if (!time_after(now, (last_post_time + HZ)))
+               return;
+
        si_meminfo(&val);
        memset(&status, 0, sizeof(struct dm_status));
        status.hdr.type = DM_STATUS_REPORT;
@@ -983,6 +996,14 @@ static void post_status(struct hv_dynmem_device *dm)
        if (status.hdr.trans_id != atomic_read(&trans_id))
                return;
 
+       /*
+        * If the last post time that we sampled has changed,
+        * we have raced, don't post the status.
+        */
+       if (last_post != last_post_time)
+               return;
+
+       last_post_time = jiffies;
        vmbus_sendpacket(dm->dev->channel, &status,
                                sizeof(struct dm_status),
                                (unsigned long)NULL,
@@ -1117,7 +1138,7 @@ static void balloon_up(struct work_struct *dummy)
 
                        if (ret == -EAGAIN)
                                msleep(20);
-
+                       post_status(&dm_device);
                } while (ret == -EAGAIN);
 
                if (ret) {
@@ -1144,8 +1165,10 @@ static void balloon_down(struct hv_dynmem_device *dm,
        struct dm_unballoon_response resp;
        int i;
 
-       for (i = 0; i < range_count; i++)
+       for (i = 0; i < range_count; i++) {
                free_balloon_pages(dm, &range_array[i]);
+               post_status(&dm_device);
+       }
 
        if (req->more_pages == 1)
                return;