hyperv-next 20220807
-----BEGIN PGP SIGNATURE----- iQFHBAABCAAxFiEEIbPD0id6easf0xsudhRwX5BBoF4FAmLwIVYTHHdlaS5saXVA a2VybmVsLm9yZwAKCRB2FHBfkEGgXsElB/9qjat7vVcjbsH965JX/iAeP0qh2mBx nq7JLIAdTGwzAPVh8abLSq9ZX5eOHSu4pW0iWf74spzCBFC5mxS5REJTJ7YzMpyF ZCVaX/fcyyklRgU4KY8mp2QlNNj8mYquJhNozdWvPgZde+l70m8bfYR3VlFHXVKj bLxxDd9C9IcOErbw4nx1qlmxLfUFTkOn559JQW7LjqBvGjnRhEYilc3niVzuM1Nn CNnJqLG2K08EbkRkXKtwtSSx8Zxh7Np/D7FeX2iUA3mH+6AbtmQIRh+4DEi3qUsG S+s62GNMoefHu9FNECHNv+sxg3M6VhJaSRfs4tSu6Gsy9YrnYnNIo6wU =/ud4 -----END PGP SIGNATURE----- Merge tag 'hyperv-next-signed-20220807' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux Pull hyperv updates from Wei Liu: "A few miscellaneous patches. There is no large patch series for this merge window" * tag 'hyperv-next-signed-20220807' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux: Drivers: hv: Create debugfs file with hyper-v balloon usage information drm/hyperv : Removing the restruction of VRAM allocation with PCI bar size PCI: hv: Take a const cpumask in hv_compose_msi_req_get_cpu() Drivers: hv: vm_bus: Handle vmbus rescind calls after vmbus is suspended
This commit is contained in:
commit
df7a456e7d
@ -171,6 +171,14 @@ int vmbus_connect(void)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
vmbus_connection.rescind_work_queue =
|
||||
create_workqueue("hv_vmbus_rescind");
|
||||
if (!vmbus_connection.rescind_work_queue) {
|
||||
ret = -ENOMEM;
|
||||
goto cleanup;
|
||||
}
|
||||
vmbus_connection.ignore_any_offer_msg = false;
|
||||
|
||||
vmbus_connection.handle_primary_chan_wq =
|
||||
create_workqueue("hv_pri_chan");
|
||||
if (!vmbus_connection.handle_primary_chan_wq) {
|
||||
@ -357,6 +365,9 @@ void vmbus_disconnect(void)
|
||||
if (vmbus_connection.handle_primary_chan_wq)
|
||||
destroy_workqueue(vmbus_connection.handle_primary_chan_wq);
|
||||
|
||||
if (vmbus_connection.rescind_work_queue)
|
||||
destroy_workqueue(vmbus_connection.rescind_work_queue);
|
||||
|
||||
if (vmbus_connection.work_queue)
|
||||
destroy_workqueue(vmbus_connection.work_queue);
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/mman.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
@ -248,7 +249,7 @@ struct dm_capabilities_resp_msg {
|
||||
* num_committed: Committed memory in pages.
|
||||
* page_file_size: The accumulated size of all page files
|
||||
* in the system in pages.
|
||||
* zero_free: The nunber of zero and free pages.
|
||||
* zero_free: The number of zero and free pages.
|
||||
* page_file_writes: The writes to the page file in pages.
|
||||
* io_diff: An indicator of file cache efficiency or page file activity,
|
||||
* calculated as File Cache Page Fault Count - Page Read Count.
|
||||
@ -567,6 +568,11 @@ struct hv_dynmem_device {
|
||||
__u32 version;
|
||||
|
||||
struct page_reporting_dev_info pr_dev_info;
|
||||
|
||||
/*
|
||||
* Maximum number of pages that can be hot_add-ed
|
||||
*/
|
||||
__u64 max_dynamic_page_count;
|
||||
};
|
||||
|
||||
static struct hv_dynmem_device dm_device;
|
||||
@ -1078,6 +1084,7 @@ static void process_info(struct hv_dynmem_device *dm, struct dm_info_msg *msg)
|
||||
|
||||
pr_info("Max. dynamic memory size: %llu MB\n",
|
||||
(*max_page_count) >> (20 - HV_HYP_PAGE_SHIFT));
|
||||
dm->max_dynamic_page_count = *max_page_count;
|
||||
}
|
||||
|
||||
break;
|
||||
@ -1116,6 +1123,19 @@ static unsigned long compute_balloon_floor(void)
|
||||
return min_pages;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute total committed memory pages
|
||||
*/
|
||||
|
||||
static unsigned long get_pages_committed(struct hv_dynmem_device *dm)
|
||||
{
|
||||
return vm_memory_committed() +
|
||||
dm->num_pages_ballooned +
|
||||
(dm->num_pages_added > dm->num_pages_onlined ?
|
||||
dm->num_pages_added - dm->num_pages_onlined : 0) +
|
||||
compute_balloon_floor();
|
||||
}
|
||||
|
||||
/*
|
||||
* Post our status as it relates memory pressure to the
|
||||
* host. Host expects the guests to post this status
|
||||
@ -1157,11 +1177,7 @@ static void post_status(struct hv_dynmem_device *dm)
|
||||
* asking us to balloon them out.
|
||||
*/
|
||||
num_pages_avail = si_mem_available();
|
||||
num_pages_committed = vm_memory_committed() +
|
||||
dm->num_pages_ballooned +
|
||||
(dm->num_pages_added > dm->num_pages_onlined ?
|
||||
dm->num_pages_added - dm->num_pages_onlined : 0) +
|
||||
compute_balloon_floor();
|
||||
num_pages_committed = get_pages_committed(dm);
|
||||
|
||||
trace_balloon_status(num_pages_avail, num_pages_committed,
|
||||
vm_memory_committed(), dm->num_pages_ballooned,
|
||||
@ -1807,6 +1823,109 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* DEBUGFS Interface
|
||||
*/
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
|
||||
/**
|
||||
* hv_balloon_debug_show - shows statistics of balloon operations.
|
||||
* @f: pointer to the &struct seq_file.
|
||||
* @offset: ignored.
|
||||
*
|
||||
* Provides the statistics that can be accessed in hv-balloon in the debugfs.
|
||||
*
|
||||
* Return: zero on success or an error code.
|
||||
*/
|
||||
static int hv_balloon_debug_show(struct seq_file *f, void *offset)
|
||||
{
|
||||
struct hv_dynmem_device *dm = f->private;
|
||||
char *sname;
|
||||
|
||||
seq_printf(f, "%-22s: %u.%u\n", "host_version",
|
||||
DYNMEM_MAJOR_VERSION(dm->version),
|
||||
DYNMEM_MINOR_VERSION(dm->version));
|
||||
|
||||
seq_printf(f, "%-22s:", "capabilities");
|
||||
if (ballooning_enabled())
|
||||
seq_puts(f, " enabled");
|
||||
|
||||
if (hot_add_enabled())
|
||||
seq_puts(f, " hot_add");
|
||||
|
||||
seq_puts(f, "\n");
|
||||
|
||||
seq_printf(f, "%-22s: %u", "state", dm->state);
|
||||
switch (dm->state) {
|
||||
case DM_INITIALIZING:
|
||||
sname = "Initializing";
|
||||
break;
|
||||
case DM_INITIALIZED:
|
||||
sname = "Initialized";
|
||||
break;
|
||||
case DM_BALLOON_UP:
|
||||
sname = "Balloon Up";
|
||||
break;
|
||||
case DM_BALLOON_DOWN:
|
||||
sname = "Balloon Down";
|
||||
break;
|
||||
case DM_HOT_ADD:
|
||||
sname = "Hot Add";
|
||||
break;
|
||||
case DM_INIT_ERROR:
|
||||
sname = "Error";
|
||||
break;
|
||||
default:
|
||||
sname = "Unknown";
|
||||
}
|
||||
seq_printf(f, " (%s)\n", sname);
|
||||
|
||||
/* HV Page Size */
|
||||
seq_printf(f, "%-22s: %ld\n", "page_size", HV_HYP_PAGE_SIZE);
|
||||
|
||||
/* Pages added with hot_add */
|
||||
seq_printf(f, "%-22s: %u\n", "pages_added", dm->num_pages_added);
|
||||
|
||||
/* pages that are "onlined"/used from pages_added */
|
||||
seq_printf(f, "%-22s: %u\n", "pages_onlined", dm->num_pages_onlined);
|
||||
|
||||
/* pages we have given back to host */
|
||||
seq_printf(f, "%-22s: %u\n", "pages_ballooned", dm->num_pages_ballooned);
|
||||
|
||||
seq_printf(f, "%-22s: %lu\n", "total_pages_committed",
|
||||
get_pages_committed(dm));
|
||||
|
||||
seq_printf(f, "%-22s: %llu\n", "max_dynamic_page_count",
|
||||
dm->max_dynamic_page_count);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_SHOW_ATTRIBUTE(hv_balloon_debug);
|
||||
|
||||
static void hv_balloon_debugfs_init(struct hv_dynmem_device *b)
|
||||
{
|
||||
debugfs_create_file("hv-balloon", 0444, NULL, b,
|
||||
&hv_balloon_debug_fops);
|
||||
}
|
||||
|
||||
static void hv_balloon_debugfs_exit(struct hv_dynmem_device *b)
|
||||
{
|
||||
debugfs_remove(debugfs_lookup("hv-balloon", NULL));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static inline void hv_balloon_debugfs_init(struct hv_dynmem_device *b)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void hv_balloon_debugfs_exit(struct hv_dynmem_device *b)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_DEBUG_FS */
|
||||
|
||||
static int balloon_probe(struct hv_device *dev,
|
||||
const struct hv_vmbus_device_id *dev_id)
|
||||
{
|
||||
@ -1854,6 +1973,8 @@ static int balloon_probe(struct hv_device *dev,
|
||||
goto probe_error;
|
||||
}
|
||||
|
||||
hv_balloon_debugfs_init(&dm_device);
|
||||
|
||||
return 0;
|
||||
|
||||
probe_error:
|
||||
@ -1879,6 +2000,8 @@ static int balloon_remove(struct hv_device *dev)
|
||||
if (dm->num_pages_ballooned != 0)
|
||||
pr_warn("Ballooned pages: %d\n", dm->num_pages_ballooned);
|
||||
|
||||
hv_balloon_debugfs_exit(dm);
|
||||
|
||||
cancel_work_sync(&dm->balloon_wrk.wrk);
|
||||
cancel_work_sync(&dm->ha_wrk.wrk);
|
||||
|
||||
|
@ -261,6 +261,13 @@ struct vmbus_connection {
|
||||
struct workqueue_struct *work_queue;
|
||||
struct workqueue_struct *handle_primary_chan_wq;
|
||||
struct workqueue_struct *handle_sub_chan_wq;
|
||||
struct workqueue_struct *rescind_work_queue;
|
||||
|
||||
/*
|
||||
* On suspension of the vmbus, the accumulated offer messages
|
||||
* must be dropped.
|
||||
*/
|
||||
bool ignore_any_offer_msg;
|
||||
|
||||
/*
|
||||
* The number of sub-channels and hv_sock channels that should be
|
||||
|
@ -1160,7 +1160,9 @@ void vmbus_on_msg_dpc(unsigned long data)
|
||||
* work queue: the RESCIND handler can not start to
|
||||
* run before the OFFER handler finishes.
|
||||
*/
|
||||
schedule_work(&ctx->work);
|
||||
if (vmbus_connection.ignore_any_offer_msg)
|
||||
break;
|
||||
queue_work(vmbus_connection.rescind_work_queue, &ctx->work);
|
||||
break;
|
||||
|
||||
case CHANNELMSG_OFFERCHANNEL:
|
||||
@ -1186,6 +1188,8 @@ void vmbus_on_msg_dpc(unsigned long data)
|
||||
* to the CPUs which will execute the offer & rescind
|
||||
* works by the time these works will start execution.
|
||||
*/
|
||||
if (vmbus_connection.ignore_any_offer_msg)
|
||||
break;
|
||||
atomic_inc(&vmbus_connection.offer_in_progress);
|
||||
fallthrough;
|
||||
|
||||
@ -2446,15 +2450,20 @@ acpi_walk_err:
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int vmbus_bus_suspend(struct device *dev)
|
||||
{
|
||||
struct hv_per_cpu_context *hv_cpu = per_cpu_ptr(
|
||||
hv_context.cpu_context, VMBUS_CONNECT_CPU);
|
||||
struct vmbus_channel *channel, *sc;
|
||||
|
||||
while (atomic_read(&vmbus_connection.offer_in_progress) != 0) {
|
||||
/*
|
||||
* We wait here until the completion of any channel
|
||||
* offers that are currently in progress.
|
||||
*/
|
||||
usleep_range(1000, 2000);
|
||||
}
|
||||
tasklet_disable(&hv_cpu->msg_dpc);
|
||||
vmbus_connection.ignore_any_offer_msg = true;
|
||||
/* The tasklet_enable() takes care of providing a memory barrier */
|
||||
tasklet_enable(&hv_cpu->msg_dpc);
|
||||
|
||||
/* Drain all the workqueues as we are in suspend */
|
||||
drain_workqueue(vmbus_connection.rescind_work_queue);
|
||||
drain_workqueue(vmbus_connection.work_queue);
|
||||
drain_workqueue(vmbus_connection.handle_primary_chan_wq);
|
||||
drain_workqueue(vmbus_connection.handle_sub_chan_wq);
|
||||
|
||||
mutex_lock(&vmbus_connection.channel_mutex);
|
||||
list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) {
|
||||
@ -2531,6 +2540,8 @@ static int vmbus_bus_resume(struct device *dev)
|
||||
size_t msgsize;
|
||||
int ret;
|
||||
|
||||
vmbus_connection.ignore_any_offer_msg = false;
|
||||
|
||||
/*
|
||||
* We only use the 'vmbus_proto_version', which was in use before
|
||||
* hibernation, to re-negotiate with the host.
|
||||
|
Loading…
x
Reference in New Issue
Block a user