25
25
#include <linux/hyperv.h>
26
26
#include <asm/hyperv-tlfs.h>
27
27
28
+ #include <asm/mshyperv.h>
29
+
28
30
#define CREATE_TRACE_POINTS
29
31
#include "hv_trace_balloon.h"
30
32
@@ -456,6 +458,7 @@ struct hot_add_wrk {
456
458
struct work_struct wrk ;
457
459
};
458
460
461
+ static bool allow_hibernation ;
459
462
static bool hot_add = true;
460
463
static bool do_hot_add ;
461
464
/*
@@ -1052,8 +1055,12 @@ static void hot_add_req(struct work_struct *dummy)
1052
1055
else
1053
1056
resp .result = 0 ;
1054
1057
1055
- if (!do_hot_add || (resp .page_count == 0 ))
1056
- pr_err ("Memory hot add failed\n" );
1058
+ if (!do_hot_add || resp .page_count == 0 ) {
1059
+ if (!allow_hibernation )
1060
+ pr_err ("Memory hot add failed\n" );
1061
+ else
1062
+ pr_info ("Ignore hot-add request!\n" );
1063
+ }
1057
1064
1058
1065
dm -> state = DM_INITIALIZED ;
1059
1066
resp .hdr .trans_id = atomic_inc_return (& trans_id );
@@ -1508,6 +1515,11 @@ static void balloon_onchannelcallback(void *context)
1508
1515
break ;
1509
1516
1510
1517
case DM_BALLOON_REQUEST :
1518
+ if (allow_hibernation ) {
1519
+ pr_info ("Ignore balloon-up request!\n" );
1520
+ break ;
1521
+ }
1522
+
1511
1523
if (dm -> state == DM_BALLOON_UP )
1512
1524
pr_warn ("Currently ballooning\n" );
1513
1525
bal_msg = (struct dm_balloon * )recv_buffer ;
@@ -1517,6 +1529,11 @@ static void balloon_onchannelcallback(void *context)
1517
1529
break ;
1518
1530
1519
1531
case DM_UNBALLOON_REQUEST :
1532
+ if (allow_hibernation ) {
1533
+ pr_info ("Ignore balloon-down request!\n" );
1534
+ break ;
1535
+ }
1536
+
1520
1537
dm -> state = DM_BALLOON_DOWN ;
1521
1538
balloon_down (dm ,
1522
1539
(struct dm_unballoon_request * )recv_buffer );
@@ -1622,6 +1639,11 @@ static int balloon_connect_vsp(struct hv_device *dev)
1622
1639
cap_msg .hdr .size = sizeof (struct dm_capabilities );
1623
1640
cap_msg .hdr .trans_id = atomic_inc_return (& trans_id );
1624
1641
1642
+ /*
1643
+ * When hibernation (i.e. virtual ACPI S4 state) is enabled, the host
1644
+ * currently still requires the bits to be set, so we have to add code
1645
+ * to fail the host's hot-add and balloon up/down requests, if any.
1646
+ */
1625
1647
cap_msg .caps .cap_bits .balloon = 1 ;
1626
1648
cap_msg .caps .cap_bits .hot_add = 1 ;
1627
1649
@@ -1671,6 +1693,10 @@ static int balloon_probe(struct hv_device *dev,
1671
1693
{
1672
1694
int ret ;
1673
1695
1696
+ allow_hibernation = hv_is_hibernation_supported ();
1697
+ if (allow_hibernation )
1698
+ hot_add = false;
1699
+
1674
1700
#ifdef CONFIG_MEMORY_HOTPLUG
1675
1701
do_hot_add = hot_add ;
1676
1702
#else
@@ -1710,6 +1736,8 @@ static int balloon_probe(struct hv_device *dev,
1710
1736
return 0 ;
1711
1737
1712
1738
probe_error :
1739
+ dm_device .state = DM_INIT_ERROR ;
1740
+ dm_device .thread = NULL ;
1713
1741
vmbus_close (dev -> channel );
1714
1742
#ifdef CONFIG_MEMORY_HOTPLUG
1715
1743
unregister_memory_notifier (& hv_memory_nb );
@@ -1751,6 +1779,59 @@ static int balloon_remove(struct hv_device *dev)
1751
1779
return 0 ;
1752
1780
}
1753
1781
1782
+ static int balloon_suspend (struct hv_device * hv_dev )
1783
+ {
1784
+ struct hv_dynmem_device * dm = hv_get_drvdata (hv_dev );
1785
+
1786
+ tasklet_disable (& hv_dev -> channel -> callback_event );
1787
+
1788
+ cancel_work_sync (& dm -> balloon_wrk .wrk );
1789
+ cancel_work_sync (& dm -> ha_wrk .wrk );
1790
+
1791
+ if (dm -> thread ) {
1792
+ kthread_stop (dm -> thread );
1793
+ dm -> thread = NULL ;
1794
+ vmbus_close (hv_dev -> channel );
1795
+ }
1796
+
1797
+ tasklet_enable (& hv_dev -> channel -> callback_event );
1798
+
1799
+ return 0 ;
1800
+
1801
+ }
1802
+
1803
+ static int balloon_resume (struct hv_device * dev )
1804
+ {
1805
+ int ret ;
1806
+
1807
+ dm_device .state = DM_INITIALIZING ;
1808
+
1809
+ ret = balloon_connect_vsp (dev );
1810
+
1811
+ if (ret != 0 )
1812
+ goto out ;
1813
+
1814
+ dm_device .thread =
1815
+ kthread_run (dm_thread_func , & dm_device , "hv_balloon" );
1816
+ if (IS_ERR (dm_device .thread )) {
1817
+ ret = PTR_ERR (dm_device .thread );
1818
+ dm_device .thread = NULL ;
1819
+ goto close_channel ;
1820
+ }
1821
+
1822
+ dm_device .state = DM_INITIALIZED ;
1823
+ return 0 ;
1824
+ close_channel :
1825
+ vmbus_close (dev -> channel );
1826
+ out :
1827
+ dm_device .state = DM_INIT_ERROR ;
1828
+ #ifdef CONFIG_MEMORY_HOTPLUG
1829
+ unregister_memory_notifier (& hv_memory_nb );
1830
+ restore_online_page_callback (& hv_online_page );
1831
+ #endif
1832
+ return ret ;
1833
+ }
1834
+
1754
1835
static const struct hv_vmbus_device_id id_table [] = {
1755
1836
/* Dynamic Memory Class ID */
1756
1837
/* 525074DC-8985-46e2-8057-A307DC18A502 */
@@ -1765,6 +1846,8 @@ static struct hv_driver balloon_drv = {
1765
1846
.id_table = id_table ,
1766
1847
.probe = balloon_probe ,
1767
1848
.remove = balloon_remove ,
1849
+ .suspend = balloon_suspend ,
1850
+ .resume = balloon_resume ,
1768
1851
.driver = {
1769
1852
.probe_type = PROBE_PREFER_ASYNCHRONOUS ,
1770
1853
},
0 commit comments