aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/xen
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/xen')
-rw-r--r--drivers/xen/Kconfig86
-rw-r--r--drivers/xen/Makefile8
-rw-r--r--drivers/xen/balloon.c215
-rw-r--r--drivers/xen/events.c131
-rw-r--r--drivers/xen/evtchn.c31
-rw-r--r--drivers/xen/gntdev.c118
-rw-r--r--drivers/xen/grant-table.c10
-rw-r--r--drivers/xen/manage.c21
-rw-r--r--drivers/xen/pci.c107
-rw-r--r--drivers/xen/swiotlb-xen.c62
-rw-r--r--drivers/xen/tmem.c170
-rw-r--r--drivers/xen/xen-balloon.c17
-rw-r--r--drivers/xen/xenbus/xenbus_client.c16
-rw-r--r--drivers/xen/xenbus/xenbus_comms.c4
-rw-r--r--drivers/xen/xenbus/xenbus_probe.c151
-rw-r--r--drivers/xen/xenbus/xenbus_probe.h5
-rw-r--r--drivers/xen/xenbus/xenbus_probe_backend.c12
-rw-r--r--drivers/xen/xenbus/xenbus_probe_frontend.c128
-rw-r--r--drivers/xen/xenbus/xenbus_xs.c4
19 files changed, 300 insertions, 996 deletions
diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig
index 8795480..a59638b 100644
--- a/drivers/xen/Kconfig
+++ b/drivers/xen/Kconfig
@@ -9,53 +9,6 @@ config XEN_BALLOON
the system to expand the domain's memory allocation, or alternatively
return unneeded memory to the system.
-config XEN_SELFBALLOONING
- bool "Dynamically self-balloon kernel memory to target"
- depends on XEN && XEN_BALLOON && CLEANCACHE && SWAP && XEN_TMEM
- default n
- help
- Self-ballooning dynamically balloons available kernel memory driven
- by the current usage of anonymous memory ("committed AS") and
- controlled by various sysfs-settable parameters. Configuring
- FRONTSWAP is highly recommended; if it is not configured, self-
- ballooning is disabled by default but can be enabled with the
- 'selfballooning' kernel boot parameter. If FRONTSWAP is configured,
- frontswap-selfshrinking is enabled by default but can be disabled
- with the 'noselfshrink' kernel boot parameter; and self-ballooning
- is enabled by default but can be disabled with the 'noselfballooning'
- kernel boot parameter. Note that systems without a sufficiently
- large swap device should not enable self-ballooning.
-
-config XEN_BALLOON_MEMORY_HOTPLUG
- bool "Memory hotplug support for Xen balloon driver"
- default n
- depends on XEN_BALLOON && MEMORY_HOTPLUG
- help
- Memory hotplug support for Xen balloon driver allows expanding memory
- available for the system above limit declared at system startup.
- It is very useful on critical systems which require long
- run without rebooting.
-
- Memory could be hotplugged in following steps:
-
- 1) dom0: xl mem-max <domU> <maxmem>
- where <maxmem> is >= requested memory size,
-
- 2) dom0: xl mem-set <domU> <memory>
- where <memory> is requested memory size; alternatively memory
- could be added by writing proper value to
- /sys/devices/system/xen_memory/xen_memory0/target or
- /sys/devices/system/xen_memory/xen_memory0/target_kb on dumU,
-
- 3) domU: for i in /sys/devices/system/memory/memory*/state; do \
- [ "`cat "$i"`" = offline ] && echo online > "$i"; done
-
- Memory could be onlined automatically on domU by adding following line to udev rules:
-
- SUBSYSTEM=="memory", ACTION=="add", RUN+="/bin/sh -c '[ -f /sys$devpath/state ] && echo online > /sys$devpath/state'"
-
- In that case step 3 should be omitted.
-
config XEN_SCRUB_PAGES
bool "Scrub pages before returning them to system"
depends on XEN_BALLOON
@@ -137,38 +90,19 @@ config XEN_GRANT_DEV_ALLOC
to other domains. This can be used to implement frontend drivers
or as part of an inter-domain shared memory channel.
+config XEN_PLATFORM_PCI
+ tristate "xen platform pci device driver"
+ depends on XEN_PVHVM && PCI
+ default m
+ help
+ Driver for the Xen PCI Platform device: it is responsible for
+ initializing xenbus and grant_table when running in a Xen HVM
+ domain. As a consequence this driver is required to run any Xen PV
+ frontend on Xen HVM.
+
config SWIOTLB_XEN
def_bool y
depends on PCI
select SWIOTLB
-config XEN_TMEM
- bool
- default y if (CLEANCACHE || FRONTSWAP)
- help
- Shim to interface in-kernel Transcendent Memory hooks
- (e.g. cleancache and frontswap) to Xen tmem hypercalls.
-
-config XEN_PCIDEV_BACKEND
- tristate "Xen PCI-device backend driver"
- depends on PCI && X86 && XEN
- depends on XEN_BACKEND
- default m
- help
- The PCI device backend driver allows the kernel to export arbitrary
- PCI devices to other guests. If you select this to be a module, you
- will need to make sure no other driver has bound to the device(s)
- you want to make visible to other guests.
-
- The parameter "passthrough" allows you specify how you want the PCI
- devices to appear in the guest. You can choose the default (0) where
- PCI topology starts at 00.00.0, or (1) for passthrough if you want
- the PCI devices topology appear the same as in the host.
-
- The "hide" parameter (only applicable if backend driver is compiled
- into the kernel) allows you to bind the PCI devices to this module
- from the default device drivers. The argument is the list of PCI BDFs:
- xen-pciback.hide=(03:00.0)(04:00.0)
-
- If in doubt, say m.
endmenu
diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile
index 974fffd..bbc1825 100644
--- a/drivers/xen/Makefile
+++ b/drivers/xen/Makefile
@@ -1,5 +1,6 @@
obj-y += grant-table.o features.o events.o manage.o balloon.o
obj-y += xenbus/
+obj-y += tmem.o
nostackp := $(call cc-option, -fno-stack-protector)
CFLAGS_features.o := $(nostackp)
@@ -8,18 +9,17 @@ obj-$(CONFIG_BLOCK) += biomerge.o
obj-$(CONFIG_HOTPLUG_CPU) += cpu_hotplug.o
obj-$(CONFIG_XEN_XENCOMM) += xencomm.o
obj-$(CONFIG_XEN_BALLOON) += xen-balloon.o
-obj-$(CONFIG_XEN_SELFBALLOONING) += xen-selfballoon.o
obj-$(CONFIG_XEN_DEV_EVTCHN) += xen-evtchn.o
obj-$(CONFIG_XEN_GNTDEV) += xen-gntdev.o
obj-$(CONFIG_XEN_GRANT_DEV_ALLOC) += xen-gntalloc.o
obj-$(CONFIG_XENFS) += xenfs/
obj-$(CONFIG_XEN_SYS_HYPERVISOR) += sys-hypervisor.o
-obj-$(CONFIG_XEN_PVHVM) += platform-pci.o
-obj-$(CONFIG_XEN_TMEM) += tmem.o
+obj-$(CONFIG_XEN_PLATFORM_PCI) += xen-platform-pci.o
obj-$(CONFIG_SWIOTLB_XEN) += swiotlb-xen.o
obj-$(CONFIG_XEN_DOM0) += pci.o
-obj-$(CONFIG_XEN_PCIDEV_BACKEND) += xen-pciback/
xen-evtchn-y := evtchn.o
xen-gntdev-y := gntdev.o
xen-gntalloc-y := gntalloc.o
+
+xen-platform-pci-y := platform-pci.o
diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c
index 31ab82f..f54290b 100644
--- a/drivers/xen/balloon.c
+++ b/drivers/xen/balloon.c
@@ -4,12 +4,6 @@
* Copyright (c) 2003, B Dragovic
* Copyright (c) 2003-2004, M Williamson, K Fraser
* Copyright (c) 2005 Dan M. Smith, IBM Corporation
- * Copyright (c) 2010 Daniel Kiper
- *
- * Memory hotplug support was written by Daniel Kiper. Work on
- * it was sponsored by Google under Google Summer of Code 2010
- * program. Jeremy Fitzhardinge from Citrix was the mentor for
- * this project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
@@ -39,7 +33,6 @@
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/errno.h>
-#include <linux/module.h>
#include <linux/mm.h>
#include <linux/bootmem.h>
#include <linux/pagemap.h>
@@ -47,9 +40,6 @@
#include <linux/mutex.h>
#include <linux/list.h>
#include <linux/gfp.h>
-#include <linux/notifier.h>
-#include <linux/memory.h>
-#include <linux/memory_hotplug.h>
#include <asm/page.h>
#include <asm/pgalloc.h>
@@ -94,8 +84,8 @@ static unsigned long frame_list[PAGE_SIZE / sizeof(unsigned long)];
#define inc_totalhigh_pages() (totalhigh_pages++)
#define dec_totalhigh_pages() (totalhigh_pages--)
#else
-#define inc_totalhigh_pages() do {} while (0)
-#define dec_totalhigh_pages() do {} while (0)
+#define inc_totalhigh_pages() do {} while(0)
+#define dec_totalhigh_pages() do {} while(0)
#endif
/* List of ballooned pages, threaded through the mem_map array. */
@@ -155,7 +145,8 @@ static struct page *balloon_retrieve(bool prefer_highmem)
if (PageHighMem(page)) {
balloon_stats.balloon_high--;
inc_totalhigh_pages();
- } else
+ }
+ else
balloon_stats.balloon_low--;
totalram_pages++;
@@ -203,87 +194,6 @@ static enum bp_state update_schedule(enum bp_state state)
return BP_EAGAIN;
}
-#ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG
-static long current_credit(void)
-{
- return balloon_stats.target_pages - balloon_stats.current_pages -
- balloon_stats.hotplug_pages;
-}
-
-static bool balloon_is_inflated(void)
-{
- if (balloon_stats.balloon_low || balloon_stats.balloon_high ||
- balloon_stats.balloon_hotplug)
- return true;
- else
- return false;
-}
-
-/*
- * reserve_additional_memory() adds memory region of size >= credit above
- * max_pfn. New region is section aligned and size is modified to be multiple
- * of section size. Those features allow optimal use of address space and
- * establish proper alignment when this function is called first time after
- * boot (last section not fully populated at boot time contains unused memory
- * pages with PG_reserved bit not set; online_pages_range() does not allow page
- * onlining in whole range if first onlined page does not have PG_reserved
- * bit set). Real size of added memory is established at page onlining stage.
- */
-
-static enum bp_state reserve_additional_memory(long credit)
-{
- int nid, rc;
- u64 hotplug_start_paddr;
- unsigned long balloon_hotplug = credit;
-
- hotplug_start_paddr = PFN_PHYS(SECTION_ALIGN_UP(max_pfn));
- balloon_hotplug = round_up(balloon_hotplug, PAGES_PER_SECTION);
- nid = memory_add_physaddr_to_nid(hotplug_start_paddr);
-
- rc = add_memory(nid, hotplug_start_paddr, balloon_hotplug << PAGE_SHIFT);
-
- if (rc) {
- pr_info("xen_balloon: %s: add_memory() failed: %i\n", __func__, rc);
- return BP_EAGAIN;
- }
-
- balloon_hotplug -= credit;
-
- balloon_stats.hotplug_pages += credit;
- balloon_stats.balloon_hotplug = balloon_hotplug;
-
- return BP_DONE;
-}
-
-static void xen_online_page(struct page *page)
-{
- __online_page_set_limits(page);
-
- mutex_lock(&balloon_mutex);
-
- __balloon_append(page);
-
- if (balloon_stats.hotplug_pages)
- --balloon_stats.hotplug_pages;
- else
- --balloon_stats.balloon_hotplug;
-
- mutex_unlock(&balloon_mutex);
-}
-
-static int xen_memory_notifier(struct notifier_block *nb, unsigned long val, void *v)
-{
- if (val == MEM_ONLINE)
- schedule_delayed_work(&balloon_worker, 0);
-
- return NOTIFY_OK;
-}
-
-static struct notifier_block xen_memory_nb = {
- .notifier_call = xen_memory_notifier,
- .priority = 0
-};
-#else
static long current_credit(void)
{
unsigned long target = balloon_stats.target_pages;
@@ -296,21 +206,6 @@ static long current_credit(void)
return target - balloon_stats.current_pages;
}
-static bool balloon_is_inflated(void)
-{
- if (balloon_stats.balloon_low || balloon_stats.balloon_high)
- return true;
- else
- return false;
-}
-
-static enum bp_state reserve_additional_memory(long credit)
-{
- balloon_stats.target_pages = balloon_stats.current_pages;
- return BP_DONE;
-}
-#endif /* CONFIG_XEN_BALLOON_MEMORY_HOTPLUG */
-
static enum bp_state increase_reservation(unsigned long nr_pages)
{
int rc;
@@ -322,15 +217,6 @@ static enum bp_state increase_reservation(unsigned long nr_pages)
.domid = DOMID_SELF
};
-#ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG
- if (!balloon_stats.balloon_low && !balloon_stats.balloon_high) {
- nr_pages = min(nr_pages, balloon_stats.balloon_hotplug);
- balloon_stats.hotplug_pages += nr_pages;
- balloon_stats.balloon_hotplug -= nr_pages;
- return BP_DONE;
- }
-#endif
-
if (nr_pages > ARRAY_SIZE(frame_list))
nr_pages = ARRAY_SIZE(frame_list);
@@ -393,15 +279,6 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp)
.domid = DOMID_SELF
};
-#ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG
- if (balloon_stats.hotplug_pages) {
- nr_pages = min(nr_pages, balloon_stats.hotplug_pages);
- balloon_stats.hotplug_pages -= nr_pages;
- balloon_stats.balloon_hotplug += nr_pages;
- return BP_DONE;
- }
-#endif
-
if (nr_pages > ARRAY_SIZE(frame_list))
nr_pages = ARRAY_SIZE(frame_list);
@@ -422,7 +299,7 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp)
(unsigned long)__va(pfn << PAGE_SHIFT),
__pte_ma(0), 0);
BUG_ON(ret);
- }
+ }
}
@@ -463,12 +340,8 @@ static void balloon_process(struct work_struct *work)
do {
credit = current_credit();
- if (credit > 0) {
- if (balloon_is_inflated())
- state = increase_reservation(credit);
- else
- state = reserve_additional_memory(credit);
- }
+ if (credit > 0)
+ state = increase_reservation(credit);
if (credit < 0)
state = decrease_reservation(-credit, GFP_BALLOON);
@@ -501,24 +374,20 @@ EXPORT_SYMBOL_GPL(balloon_set_new_target);
* alloc_xenballooned_pages - get pages that have been ballooned out
* @nr_pages: Number of pages to get
* @pages: pages returned
- * @highmem: allow highmem pages
* @return 0 on success, error otherwise
*/
-int alloc_xenballooned_pages(int nr_pages, struct page **pages, bool highmem)
+int alloc_xenballooned_pages(int nr_pages, struct page** pages)
{
int pgno = 0;
- struct page *page;
+ struct page* page;
mutex_lock(&balloon_mutex);
while (pgno < nr_pages) {
- page = balloon_retrieve(highmem);
- if (page && (highmem || !PageHighMem(page))) {
+ page = balloon_retrieve(true);
+ if (page) {
pages[pgno++] = page;
} else {
enum bp_state st;
- if (page)
- balloon_append(page);
- st = decrease_reservation(nr_pages - pgno,
- highmem ? GFP_HIGHUSER : GFP_USER);
+ st = decrease_reservation(nr_pages - pgno, GFP_HIGHUSER);
if (st != BP_DONE)
goto out_undo;
}
@@ -540,7 +409,7 @@ EXPORT_SYMBOL(alloc_xenballooned_pages);
* @nr_pages: Number of pages
* @pages: pages to return
*/
-void free_xenballooned_pages(int nr_pages, struct page **pages)
+void free_xenballooned_pages(int nr_pages, struct page** pages)
{
int i;
@@ -559,40 +428,17 @@ void free_xenballooned_pages(int nr_pages, struct page **pages)
}
EXPORT_SYMBOL(free_xenballooned_pages);
-static void __init balloon_add_region(unsigned long start_pfn,
- unsigned long pages)
+static int __init balloon_init(void)
{
unsigned long pfn, extra_pfn_end;
struct page *page;
- /*
- * If the amount of usable memory has been limited (e.g., with
- * the 'mem' command line parameter), don't add pages beyond
- * this limit.
- */
- extra_pfn_end = min(max_pfn, start_pfn + pages);
-
- for (pfn = start_pfn; pfn < extra_pfn_end; pfn++) {
- page = pfn_to_page(pfn);
- /* totalram_pages and totalhigh_pages do not
- include the boot-time balloon extension, so
- don't subtract from it. */
- __balloon_append(page);
- }
-}
-
-static int __init balloon_init(void)
-{
- int i;
-
if (!xen_domain())
return -ENODEV;
pr_info("xen/balloon: Initialising balloon driver.\n");
- balloon_stats.current_pages = xen_pv_domain()
- ? min(xen_start_info->nr_pages - xen_released_pages, max_pfn)
- : max_pfn;
+ balloon_stats.current_pages = xen_pv_domain() ? min(xen_start_info->nr_pages, max_pfn) : max_pfn;
balloon_stats.target_pages = balloon_stats.current_pages;
balloon_stats.balloon_low = 0;
balloon_stats.balloon_high = 0;
@@ -602,22 +448,25 @@ static int __init balloon_init(void)
balloon_stats.retry_count = 1;
balloon_stats.max_retry_count = RETRY_UNLIMITED;
-#ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG
- balloon_stats.hotplug_pages = 0;
- balloon_stats.balloon_hotplug = 0;
-
- set_online_page_callback(&xen_online_page);
- register_memory_notifier(&xen_memory_nb);
-#endif
-
/*
- * Initialize the balloon with pages from the extra memory
- * regions (see arch/x86/xen/setup.c).
+ * Initialise the balloon with excess memory space. We need
+ * to make sure we don't add memory which doesn't exist or
+ * logically exist. The E820 map can be trimmed to be smaller
+ * than the amount of physical memory due to the mem= command
+ * line parameter. And if this is a 32-bit non-HIGHMEM kernel
+ * on a system with memory which requires highmem to access,
+ * don't try to use it.
*/
- for (i = 0; i < XEN_EXTRA_MEM_MAX_REGIONS; i++)
- if (xen_extra_mem[i].size)
- balloon_add_region(PFN_UP(xen_extra_mem[i].start),
- PFN_DOWN(xen_extra_mem[i].size));
+ extra_pfn_end = min(min(max_pfn, e820_end_of_ram_pfn()),
+ (unsigned long)PFN_DOWN(xen_extra_mem_start + xen_extra_mem_size));
+ for (pfn = PFN_UP(xen_extra_mem_start);
+ pfn < extra_pfn_end;
+ pfn++) {
+ page = pfn_to_page(pfn);
+ /* totalram_pages and totalhigh_pages do not include the boot-time
+ balloon extension, so don't subtract from it. */
+ __balloon_append(page);
+ }
return 0;
}
diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index bcf7711..7ba4d0e 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -54,7 +54,7 @@
* This lock protects updates to the following mapping and reference-count
* arrays. The lock does not need to be acquired to read the mapping tables.
*/
-static DEFINE_MUTEX(irq_mapping_update_lock);
+static DEFINE_SPINLOCK(irq_mapping_update_lock);
static LIST_HEAD(xen_irq_list_head);
@@ -85,7 +85,8 @@ enum xen_irq_type {
* IPI - IPI vector
* EVTCHN -
*/
-struct irq_info {
+struct irq_info
+{
struct list_head list;
enum xen_irq_type type; /* type */
unsigned irq;
@@ -281,9 +282,9 @@ static inline unsigned long active_evtchns(unsigned int cpu,
struct shared_info *sh,
unsigned int idx)
{
- return sh->evtchn_pending[idx] &
+ return (sh->evtchn_pending[idx] &
per_cpu(cpu_evtchn_mask, cpu)[idx] &
- ~sh->evtchn_mask[idx];
+ ~sh->evtchn_mask[idx]);
}
static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu)
@@ -431,8 +432,7 @@ static int __must_check xen_allocate_irq_dynamic(void)
irq = irq_alloc_desc_from(first, -1);
- if (irq >= 0)
- xen_irq_init(irq);
+ xen_irq_init(irq);
return irq;
}
@@ -600,7 +600,7 @@ static void disable_pirq(struct irq_data *data)
disable_dynirq(data);
}
-int xen_irq_from_gsi(unsigned gsi)
+static int find_irq_by_gsi(unsigned gsi)
{
struct irq_info *info;
@@ -614,7 +614,11 @@ int xen_irq_from_gsi(unsigned gsi)
return -1;
}
-EXPORT_SYMBOL_GPL(xen_irq_from_gsi);
+
+int xen_allocate_pirq_gsi(unsigned gsi)
+{
+ return gsi;
+}
/*
* Do not make any assumptions regarding the relationship between the
@@ -632,9 +636,9 @@ int xen_bind_pirq_gsi_to_irq(unsigned gsi,
int irq = -1;
struct physdev_irq irq_op;
- mutex_lock(&irq_mapping_update_lock);
+ spin_lock(&irq_mapping_update_lock);
- irq = xen_irq_from_gsi(gsi);
+ irq = find_irq_by_gsi(gsi);
if (irq != -1) {
printk(KERN_INFO "xen_map_pirq_gsi: returning irq %d for gsi %u\n",
irq, gsi);
@@ -685,7 +689,7 @@ int xen_bind_pirq_gsi_to_irq(unsigned gsi,
handle_edge_irq, name);
out:
- mutex_unlock(&irq_mapping_update_lock);
+ spin_unlock(&irq_mapping_update_lock);
return irq;
}
@@ -711,10 +715,10 @@ int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc,
{
int irq, ret;
- mutex_lock(&irq_mapping_update_lock);
+ spin_lock(&irq_mapping_update_lock);
irq = xen_allocate_irq_dynamic();
- if (irq < 0)
+ if (irq == -1)
goto out;
irq_set_chip_and_handler_name(irq, &xen_pirq_chip, handle_edge_irq,
@@ -725,12 +729,12 @@ int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc,
if (ret < 0)
goto error_irq;
out:
- mutex_unlock(&irq_mapping_update_lock);
+ spin_unlock(&irq_mapping_update_lock);
return irq;
error_irq:
- mutex_unlock(&irq_mapping_update_lock);
+ spin_unlock(&irq_mapping_update_lock);
xen_free_irq(irq);
- return ret;
+ return -1;
}
#endif
@@ -741,7 +745,7 @@ int xen_destroy_irq(int irq)
struct irq_info *info = info_for_irq(irq);
int rc = -ENOENT;
- mutex_lock(&irq_mapping_update_lock);
+ spin_lock(&irq_mapping_update_lock);
desc = irq_to_desc(irq);
if (!desc)
@@ -767,7 +771,7 @@ int xen_destroy_irq(int irq)
xen_free_irq(irq);
out:
- mutex_unlock(&irq_mapping_update_lock);
+ spin_unlock(&irq_mapping_update_lock);
return rc;
}
@@ -777,10 +781,10 @@ int xen_irq_from_pirq(unsigned pirq)
struct irq_info *info;
- mutex_lock(&irq_mapping_update_lock);
+ spin_lock(&irq_mapping_update_lock);
list_for_each_entry(info, &xen_irq_list_head, list) {
- if (info->type != IRQT_PIRQ)
+ if (info == NULL || info->type != IRQT_PIRQ)
continue;
irq = info->irq;
if (info->u.pirq.pirq == pirq)
@@ -788,7 +792,7 @@ int xen_irq_from_pirq(unsigned pirq)
}
irq = -1;
out:
- mutex_unlock(&irq_mapping_update_lock);
+ spin_unlock(&irq_mapping_update_lock);
return irq;
}
@@ -803,7 +807,7 @@ int bind_evtchn_to_irq(unsigned int evtchn)
{
int irq;
- mutex_lock(&irq_mapping_update_lock);
+ spin_lock(&irq_mapping_update_lock);
irq = evtchn_to_irq[evtchn];
@@ -819,7 +823,7 @@ int bind_evtchn_to_irq(unsigned int evtchn)
}
out:
- mutex_unlock(&irq_mapping_update_lock);
+ spin_unlock(&irq_mapping_update_lock);
return irq;
}
@@ -830,7 +834,7 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu)
struct evtchn_bind_ipi bind_ipi;
int evtchn, irq;
- mutex_lock(&irq_mapping_update_lock);
+ spin_lock(&irq_mapping_update_lock);
irq = per_cpu(ipi_to_irq, cpu)[ipi];
@@ -854,7 +858,7 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu)
}
out:
- mutex_unlock(&irq_mapping_update_lock);
+ spin_unlock(&irq_mapping_update_lock);
return irq;
}
@@ -873,34 +877,13 @@ static int bind_interdomain_evtchn_to_irq(unsigned int remote_domain,
return err ? : bind_evtchn_to_irq(bind_interdomain.local_port);
}
-static int find_virq(unsigned int virq, unsigned int cpu)
-{
- struct evtchn_status status;
- int port, rc = -ENOENT;
- memset(&status, 0, sizeof(status));
- for (port = 0; port <= NR_EVENT_CHANNELS; port++) {
- status.dom = DOMID_SELF;
- status.port = port;
- rc = HYPERVISOR_event_channel_op(EVTCHNOP_status, &status);
- if (rc < 0)
- continue;
- if (status.status != EVTCHNSTAT_virq)
- continue;
- if (status.u.virq == virq && status.vcpu == cpu) {
- rc = port;
- break;
- }
- }
- return rc;
-}
-
-int bind_virq_to_irq(unsigned int virq, unsigned int cpu, bool percpu)
+int bind_virq_to_irq(unsigned int virq, unsigned int cpu)
{
struct evtchn_bind_virq bind_virq;
- int evtchn, irq, ret;
+ int evtchn, irq;
- mutex_lock(&irq_mapping_update_lock);
+ spin_lock(&irq_mapping_update_lock);
irq = per_cpu(virq_to_irq, cpu)[virq];
@@ -909,25 +892,15 @@ int bind_virq_to_irq(unsigned int virq, unsigned int cpu, bool percpu)
if (irq == -1)
goto out;
- if (percpu)
- irq_set_chip_and_handler_name(irq, &xen_percpu_chip,
- handle_percpu_irq, "virq");
- else
- irq_set_chip_and_handler_name(irq, &xen_dynamic_chip,
- handle_edge_irq, "virq");
+ irq_set_chip_and_handler_name(irq, &xen_percpu_chip,
+ handle_percpu_irq, "virq");
bind_virq.virq = virq;
bind_virq.vcpu = cpu;
- ret = HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq,
- &bind_virq);
- if (ret == 0)
- evtchn = bind_virq.port;
- else {
- if (ret == -EEXIST)
- ret = find_virq(virq, cpu);
- BUG_ON(ret < 0);
- evtchn = ret;
- }
+ if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq,
+ &bind_virq) != 0)
+ BUG();
+ evtchn = bind_virq.port;
xen_irq_info_virq_init(cpu, irq, evtchn, virq);
@@ -935,7 +908,7 @@ int bind_virq_to_irq(unsigned int virq, unsigned int cpu, bool percpu)
}
out:
- mutex_unlock(&irq_mapping_update_lock);
+ spin_unlock(&irq_mapping_update_lock);
return irq;
}
@@ -945,7 +918,7 @@ static void unbind_from_irq(unsigned int irq)
struct evtchn_close close;
int evtchn = evtchn_from_irq(irq);
- mutex_lock(&irq_mapping_update_lock);
+ spin_lock(&irq_mapping_update_lock);
if (VALID_EVTCHN(evtchn)) {
close.port = evtchn;
@@ -975,7 +948,7 @@ static void unbind_from_irq(unsigned int irq)
xen_free_irq(irq);
- mutex_unlock(&irq_mapping_update_lock);
+ spin_unlock(&irq_mapping_update_lock);
}
int bind_evtchn_to_irqhandler(unsigned int evtchn,
@@ -1027,7 +1000,7 @@ int bind_virq_to_irqhandler(unsigned int virq, unsigned int cpu,
{
int irq, retval;
- irq = bind_virq_to_irq(virq, cpu, irqflags & IRQF_PERCPU);
+ irq = bind_virq_to_irq(virq, cpu);
if (irq < 0)
return irq;
retval = request_irq(irq, handler, irqflags, devname, dev_id);
@@ -1184,7 +1157,7 @@ static void __xen_evtchn_do_upcall(void)
int cpu = get_cpu();
struct shared_info *s = HYPERVISOR_shared_info;
struct vcpu_info *vcpu_info = __this_cpu_read(xen_vcpu);
- unsigned count;
+ unsigned count;
do {
unsigned long pending_words;
@@ -1322,7 +1295,7 @@ void rebind_evtchn_irq(int evtchn, int irq)
will also be masked. */
disable_irq(irq);
- mutex_lock(&irq_mapping_update_lock);
+ spin_lock(&irq_mapping_update_lock);
/* After resume the irq<->evtchn mappings are all cleared out */
BUG_ON(evtchn_to_irq[evtchn] != -1);
@@ -1332,7 +1305,7 @@ void rebind_evtchn_irq(int evtchn, int irq)
xen_irq_info_evtchn_init(irq, evtchn);
- mutex_unlock(&irq_mapping_update_lock);
+ spin_unlock(&irq_mapping_update_lock);
/* new event channels are always bound to cpu 0 */
irq_set_affinity(irq, cpumask_of(0));
@@ -1344,10 +1317,8 @@ void rebind_evtchn_irq(int evtchn, int irq)
/* Rebind an evtchn so that it gets delivered to a specific cpu */
static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
{
- struct shared_info *s = HYPERVISOR_shared_info;
struct evtchn_bind_vcpu bind_vcpu;
int evtchn = evtchn_from_irq(irq);
- int masked;
if (!VALID_EVTCHN(evtchn))
return -1;
@@ -1364,12 +1335,6 @@ static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
bind_vcpu.vcpu = tcpu;
/*
- * Mask the event while changing the VCPU binding to prevent
- * it being delivered on an unexpected VCPU.
- */
- masked = sync_test_and_set_bit(evtchn, s->evtchn_mask);
-
- /*
* If this fails, it usually just indicates that we're dealing with a
* virq or IPI channel, which don't actually need to be rebound. Ignore
* it, but don't do the xenlinux-level rebind in that case.
@@ -1377,9 +1342,6 @@ static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_vcpu, &bind_vcpu) >= 0)
bind_evtchn_to_cpu(evtchn, tcpu);
- if (!masked)
- unmask_evtchn(evtchn);
-
return 0;
}
@@ -1724,7 +1686,6 @@ void __init xen_init_IRQ(void)
evtchn_to_irq = kcalloc(NR_EVENT_CHANNELS, sizeof(*evtchn_to_irq),
GFP_KERNEL);
- BUG_ON(!evtchn_to_irq);
for (i = 0; i < NR_EVENT_CHANNELS; i++)
evtchn_to_irq[i] = -1;
@@ -1743,6 +1704,6 @@ void __init xen_init_IRQ(void)
} else {
irq_ctx_init(smp_processor_id());
if (xen_initial_domain())
- pci_xen_initial_domain();
+ xen_setup_pirqs();
}
}
diff --git a/drivers/xen/evtchn.c b/drivers/xen/evtchn.c
index c93d59e..ce3a0f5 100644
--- a/drivers/xen/evtchn.c
+++ b/drivers/xen/evtchn.c
@@ -269,14 +269,6 @@ static int evtchn_bind_to_user(struct per_user_data *u, int port)
u->name, (void *)(unsigned long)port);
if (rc >= 0)
rc = 0;
- else {
- /* bind failed, should close the port now */
- struct evtchn_close close;
- close.port = port;
- if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0)
- BUG();
- set_port_user(port, NULL);
- }
return rc;
}
@@ -285,8 +277,6 @@ static void evtchn_unbind_from_user(struct per_user_data *u, int port)
{
int irq = irq_from_evtchn(port);
- BUG_ON(irq < 0);
-
unbind_from_irqhandler(irq, (void *)(unsigned long)port);
set_port_user(port, NULL);
@@ -377,18 +367,12 @@ static long evtchn_ioctl(struct file *file,
if (unbind.port >= NR_EVENT_CHANNELS)
break;
- spin_lock_irq(&port_user_lock);
-
rc = -ENOTCONN;
- if (get_port_user(unbind.port) != u) {
- spin_unlock_irq(&port_user_lock);
+ if (get_port_user(unbind.port) != u)
break;
- }
disable_irq(irq_from_evtchn(unbind.port));
- spin_unlock_irq(&port_user_lock);
-
evtchn_unbind_from_user(u, unbind.port);
rc = 0;
@@ -488,26 +472,15 @@ static int evtchn_release(struct inode *inode, struct file *filp)
int i;
struct per_user_data *u = filp->private_data;
- spin_lock_irq(&port_user_lock);
-
- free_page((unsigned long)u->ring);
-
for (i = 0; i < NR_EVENT_CHANNELS; i++) {
if (get_port_user(i) != u)
continue;
disable_irq(irq_from_evtchn(i));
- }
-
- spin_unlock_irq(&port_user_lock);
-
- for (i = 0; i < NR_EVENT_CHANNELS; i++) {
- if (get_port_user(i) != u)
- continue;
-
evtchn_unbind_from_user(get_port_user(i), i);
}
+ free_page((unsigned long)u->ring);
kfree(u->name);
kfree(u);
diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c
index 5027662..b4e830e 100644
--- a/drivers/xen/gntdev.c
+++ b/drivers/xen/gntdev.c
@@ -60,7 +60,7 @@ static int use_ptemod;
struct gntdev_priv {
struct list_head maps;
/* lock protects maps from concurrent changes */
- struct mutex lock;
+ spinlock_t lock;
struct mm_struct *mm;
struct mmu_notifier mn;
};
@@ -83,7 +83,6 @@ struct grant_map {
struct ioctl_gntdev_grant_ref *grants;
struct gnttab_map_grant_ref *map_ops;
struct gnttab_unmap_grant_ref *unmap_ops;
- struct gnttab_map_grant_ref *kmap_ops;
struct page **pages;
};
@@ -105,21 +104,6 @@ static void gntdev_print_maps(struct gntdev_priv *priv,
#endif
}
-static void gntdev_free_map(struct grant_map *map)
-{
- if (map == NULL)
- return;
-
- if (map->pages)
- free_xenballooned_pages(map->count, map->pages);
- kfree(map->pages);
- kfree(map->grants);
- kfree(map->map_ops);
- kfree(map->unmap_ops);
- kfree(map->kmap_ops);
- kfree(map);
-}
-
static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count)
{
struct grant_map *add;
@@ -129,25 +113,22 @@ static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count)
if (NULL == add)
return NULL;
- add->grants = kcalloc(count, sizeof(add->grants[0]), GFP_KERNEL);
- add->map_ops = kcalloc(count, sizeof(add->map_ops[0]), GFP_KERNEL);
- add->unmap_ops = kcalloc(count, sizeof(add->unmap_ops[0]), GFP_KERNEL);
- add->kmap_ops = kcalloc(count, sizeof(add->kmap_ops[0]), GFP_KERNEL);
- add->pages = kcalloc(count, sizeof(add->pages[0]), GFP_KERNEL);
+ add->grants = kzalloc(sizeof(add->grants[0]) * count, GFP_KERNEL);
+ add->map_ops = kzalloc(sizeof(add->map_ops[0]) * count, GFP_KERNEL);
+ add->unmap_ops = kzalloc(sizeof(add->unmap_ops[0]) * count, GFP_KERNEL);
+ add->pages = kzalloc(sizeof(add->pages[0]) * count, GFP_KERNEL);
if (NULL == add->grants ||
NULL == add->map_ops ||
NULL == add->unmap_ops ||
- NULL == add->kmap_ops ||
NULL == add->pages)
goto err;
- if (alloc_xenballooned_pages(count, add->pages, false /* lowmem */))
+ if (alloc_xenballooned_pages(count, add->pages))
goto err;
for (i = 0; i < count; i++) {
add->map_ops[i].handle = -1;
add->unmap_ops[i].handle = -1;
- add->kmap_ops[i].handle = -1;
}
add->index = 0;
@@ -157,7 +138,11 @@ static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count)
return add;
err:
- gntdev_free_map(add);
+ kfree(add->pages);
+ kfree(add->grants);
+ kfree(add->map_ops);
+ kfree(add->unmap_ops);
+ kfree(add);
return NULL;
}
@@ -203,12 +188,21 @@ static void gntdev_put_map(struct grant_map *map)
atomic_sub(map->count, &pages_mapped);
- if (map->notify.flags & UNMAP_NOTIFY_SEND_EVENT)
+ if (map->notify.flags & UNMAP_NOTIFY_SEND_EVENT) {
notify_remote_via_evtchn(map->notify.event);
+ }
+
+ if (map->pages) {
+ if (!use_ptemod)
+ unmap_grant_pages(map, 0, map->count);
- if (map->pages && !use_ptemod)
- unmap_grant_pages(map, 0, map->count);
- gntdev_free_map(map);
+ free_xenballooned_pages(map->count, map->pages);
+ }
+ kfree(map->pages);
+ kfree(map->grants);
+ kfree(map->map_ops);
+ kfree(map->unmap_ops);
+ kfree(map);
}
/* ------------------------------------------------------------------ */
@@ -249,35 +243,10 @@ static int map_grant_pages(struct grant_map *map)
gnttab_set_unmap_op(&map->unmap_ops[i], addr,
map->flags, -1 /* handle */);
}
- } else {
- /*
- * Setup the map_ops corresponding to the pte entries pointing
- * to the kernel linear addresses of the struct pages.
- * These ptes are completely different from the user ptes dealt
- * with find_grant_ptes.
- */
- for (i = 0; i < map->count; i++) {
- unsigned level;
- unsigned long address = (unsigned long)
- pfn_to_kaddr(page_to_pfn(map->pages[i]));
- pte_t *ptep;
- u64 pte_maddr = 0;
- BUG_ON(PageHighMem(map->pages[i]));
-
- ptep = lookup_address(address, &level);
- pte_maddr = arbitrary_virt_to_machine(ptep).maddr;
- gnttab_set_map_op(&map->kmap_ops[i], pte_maddr,
- map->flags |
- GNTMAP_host_map |
- GNTMAP_contains_pte,
- map->grants[i].ref,
- map->grants[i].domid);
- }
}
pr_debug("map %d+%d\n", map->index, map->count);
- err = gnttab_map_refs(map->map_ops, use_ptemod ? map->kmap_ops : NULL,
- map->pages, map->count);
+ err = gnttab_map_refs(map->map_ops, map->pages, map->count);
if (err)
return err;
@@ -395,7 +364,7 @@ static void mn_invl_range_start(struct mmu_notifier *mn,
unsigned long mstart, mend;
int err;
- mutex_lock(&priv->lock);
+ spin_lock(&priv->lock);
list_for_each_entry(map, &priv->maps, next) {
if (!map->vma)
continue;
@@ -414,7 +383,7 @@ static void mn_invl_range_start(struct mmu_notifier *mn,
(mend - mstart) >> PAGE_SHIFT);
WARN_ON(err);
}
- mutex_unlock(&priv->lock);
+ spin_unlock(&priv->lock);
}
static void mn_invl_page(struct mmu_notifier *mn,
@@ -431,7 +400,7 @@ static void mn_release(struct mmu_notifier *mn,
struct grant_map *map;
int err;
- mutex_lock(&priv->lock);
+ spin_lock(&priv->lock);
list_for_each_entry(map, &priv->maps, next) {
if (!map->vma)
continue;
@@ -441,7 +410,7 @@ static void mn_release(struct mmu_notifier *mn,
err = unmap_grant_pages(map, /* offset */ 0, map->count);
WARN_ON(err);
}
- mutex_unlock(&priv->lock);
+ spin_unlock(&priv->lock);
}
struct mmu_notifier_ops gntdev_mmu_ops = {
@@ -462,7 +431,7 @@ static int gntdev_open(struct inode *inode, struct file *flip)
return -ENOMEM;
INIT_LIST_HEAD(&priv->maps);
- mutex_init(&priv->lock);
+ spin_lock_init(&priv->lock);
if (use_ptemod) {
priv->mm = get_task_mm(current);
@@ -493,13 +462,13 @@ static int gntdev_release(struct inode *inode, struct file *flip)
pr_debug("priv %p\n", priv);
- mutex_lock(&priv->lock);
+ spin_lock(&priv->lock);
while (!list_empty(&priv->maps)) {
map = list_entry(priv->maps.next, struct grant_map, next);
list_del(&map->next);
gntdev_put_map(map);
}
- mutex_unlock(&priv->lock);
+ spin_unlock(&priv->lock);
if (use_ptemod)
mmu_notifier_unregister(&priv->mn, priv->mm);
@@ -537,10 +506,10 @@ static long gntdev_ioctl_map_grant_ref(struct gntdev_priv *priv,
return err;
}
- mutex_lock(&priv->lock);
+ spin_lock(&priv->lock);
gntdev_add_map(priv, map);
op.index = map->index << PAGE_SHIFT;
- mutex_unlock(&priv->lock);
+ spin_unlock(&priv->lock);
if (copy_to_user(u, &op, sizeof(op)) != 0)
return -EFAULT;
@@ -559,15 +528,14 @@ static long gntdev_ioctl_unmap_grant_ref(struct gntdev_priv *priv,
return -EFAULT;
pr_debug("priv %p, del %d+%d\n", priv, (int)op.index, (int)op.count);
- mutex_lock(&priv->lock);
+ spin_lock(&priv->lock);
map = gntdev_find_map_index(priv, op.index >> PAGE_SHIFT, op.count);
if (map) {
list_del(&map->next);
+ gntdev_put_map(map);
err = 0;
}
- mutex_unlock(&priv->lock);
- if (map)
- gntdev_put_map(map);
+ spin_unlock(&priv->lock);
return err;
}
@@ -610,7 +578,7 @@ static long gntdev_ioctl_notify(struct gntdev_priv *priv, void __user *u)
if (op.action & ~(UNMAP_NOTIFY_CLEAR_BYTE|UNMAP_NOTIFY_SEND_EVENT))
return -EINVAL;
- mutex_lock(&priv->lock);
+ spin_lock(&priv->lock);
list_for_each_entry(map, &priv->maps, next) {
uint64_t begin = map->index << PAGE_SHIFT;
@@ -633,7 +601,7 @@ static long gntdev_ioctl_notify(struct gntdev_priv *priv, void __user *u)
map->notify.event = op.event_channel_port;
rc = 0;
unlock_out:
- mutex_unlock(&priv->lock);
+ spin_unlock(&priv->lock);
return rc;
}
@@ -678,7 +646,7 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma)
pr_debug("map %d+%d at %lx (pgoff %lx)\n",
index, count, vma->vm_start, vma->vm_pgoff);
- mutex_lock(&priv->lock);
+ spin_lock(&priv->lock);
map = gntdev_find_map_index(priv, index, count);
if (!map)
goto unlock_out;
@@ -713,7 +681,7 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma)
map->flags |= GNTMAP_readonly;
}
- mutex_unlock(&priv->lock);
+ spin_unlock(&priv->lock);
if (use_ptemod) {
err = apply_to_page_range(vma->vm_mm, vma->vm_start,
@@ -741,11 +709,11 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma)
return 0;
unlock_out:
- mutex_unlock(&priv->lock);
+ spin_unlock(&priv->lock);
return err;
out_unlock_put:
- mutex_unlock(&priv->lock);
+ spin_unlock(&priv->lock);
out_put_map:
if (use_ptemod)
map->vma = NULL;
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
index b657de6..949af52 100644
--- a/drivers/xen/grant-table.c
+++ b/drivers/xen/grant-table.c
@@ -82,7 +82,7 @@ static inline grant_ref_t *__gnttab_entry(grant_ref_t entry)
static int get_free_entries(unsigned count)
{
unsigned long flags;
- int ref, rc = 0;
+ int ref, rc;
grant_ref_t head;
spin_lock_irqsave(&gnttab_list_lock, flags);
@@ -193,7 +193,7 @@ int gnttab_query_foreign_access(grant_ref_t ref)
nflags = shared[ref].flags;
- return nflags & (GTF_reading|GTF_writing);
+ return (nflags & (GTF_reading|GTF_writing));
}
EXPORT_SYMBOL_GPL(gnttab_query_foreign_access);
@@ -457,8 +457,7 @@ unsigned int gnttab_max_grant_frames(void)
EXPORT_SYMBOL_GPL(gnttab_max_grant_frames);
int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
- struct gnttab_map_grant_ref *kmap_ops,
- struct page **pages, unsigned int count)
+ struct page **pages, unsigned int count)
{
int i, ret;
pte_t *pte;
@@ -498,7 +497,8 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
*/
return -EOPNOTSUPP;
}
- ret = m2p_add_override(mfn, pages[i], &kmap_ops[i]);
+ ret = m2p_add_override(mfn, pages[i],
+ map_ops[i].flags & GNTMAP_contains_pte);
if (ret)
return ret;
}
diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c
index caa3969..0b5366b 100644
--- a/drivers/xen/manage.c
+++ b/drivers/xen/manage.c
@@ -9,7 +9,6 @@
#include <linux/stop_machine.h>
#include <linux/freezer.h>
#include <linux/syscore_ops.h>
-#include <linux/export.h>
#include <xen/xen.h>
#include <xen/xenbus.h>
@@ -93,6 +92,7 @@ static int xen_suspend(void *data)
if (!si->cancelled) {
xen_irq_resume();
+ xen_console_resume();
xen_timer_resume();
}
@@ -108,17 +108,16 @@ static void do_suspend(void)
shutting_down = SHUTDOWN_SUSPEND;
+#ifdef CONFIG_PREEMPT
+ /* If the kernel is preemptible, we need to freeze all the processes
+ to prevent them from being in the middle of a pagetable update
+ during suspend. */
err = freeze_processes();
if (err) {
- pr_err("%s: freeze processes failed %d\n", __func__, err);
+ printk(KERN_ERR "xen suspend: freeze failed %d\n", err);
goto out;
}
-
- err = freeze_kernel_threads();
- if (err) {
- pr_err("%s: freeze kernel threads failed %d\n", __func__, err);
- goto out_thaw;
- }
+#endif
err = dpm_suspend_start(PMSG_FREEZE);
if (err) {
@@ -149,10 +148,6 @@ static void do_suspend(void)
err = stop_machine(xen_suspend, &si, cpumask_of(0));
- /* Resume console as early as possible. */
- if (!si.cancelled)
- xen_console_resume();
-
dpm_resume_noirq(si.cancelled ? PMSG_THAW : PMSG_RESTORE);
if (err) {
@@ -173,8 +168,10 @@ out_resume:
clock_was_set();
out_thaw:
+#ifdef CONFIG_PREEMPT
thaw_processes();
out:
+#endif
shutting_down = SHUTDOWN_INVALID;
}
#endif /* CONFIG_HIBERNATE_CALLBACKS */
diff --git a/drivers/xen/pci.c b/drivers/xen/pci.c
index b84bf0b..cef4baf 100644
--- a/drivers/xen/pci.c
+++ b/drivers/xen/pci.c
@@ -18,7 +18,6 @@
*/
#include <linux/pci.h>
-#include <linux/acpi.h>
#include <xen/xen.h>
#include <xen/interface/physdev.h>
#include <xen/interface/xen.h>
@@ -27,85 +26,26 @@
#include <asm/xen/hypercall.h>
#include "../pci/pci.h"
-static bool __read_mostly pci_seg_supported = true;
-
static int xen_add_device(struct device *dev)
{
int r;
struct pci_dev *pci_dev = to_pci_dev(dev);
-#ifdef CONFIG_PCI_IOV
- struct pci_dev *physfn = pci_dev->physfn;
-#endif
-
- if (pci_seg_supported) {
- struct physdev_pci_device_add add = {
- .seg = pci_domain_nr(pci_dev->bus),
- .bus = pci_dev->bus->number,
- .devfn = pci_dev->devfn
- };
-#ifdef CONFIG_ACPI
- acpi_handle handle;
-#endif
-
-#ifdef CONFIG_PCI_IOV
- if (pci_dev->is_virtfn) {
- add.flags = XEN_PCI_DEV_VIRTFN;
- add.physfn.bus = physfn->bus->number;
- add.physfn.devfn = physfn->devfn;
- } else
-#endif
- if (pci_ari_enabled(pci_dev->bus) && PCI_SLOT(pci_dev->devfn))
- add.flags = XEN_PCI_DEV_EXTFN;
-
-#ifdef CONFIG_ACPI
- handle = DEVICE_ACPI_HANDLE(&pci_dev->dev);
- if (!handle)
- handle = DEVICE_ACPI_HANDLE(pci_dev->bus->bridge);
-#ifdef CONFIG_PCI_IOV
- if (!handle && pci_dev->is_virtfn)
- handle = DEVICE_ACPI_HANDLE(physfn->bus->bridge);
-#endif
- if (handle) {
- acpi_status status;
-
- do {
- unsigned long long pxm;
-
- status = acpi_evaluate_integer(handle, "_PXM",
- NULL, &pxm);
- if (ACPI_SUCCESS(status)) {
- add.optarr[0] = pxm;
- add.flags |= XEN_PCI_DEV_PXM;
- break;
- }
- status = acpi_get_parent(handle, &handle);
- } while (ACPI_SUCCESS(status));
- }
-#endif /* CONFIG_ACPI */
-
- r = HYPERVISOR_physdev_op(PHYSDEVOP_pci_device_add, &add);
- if (r != -ENOSYS)
- return r;
- pci_seg_supported = false;
- }
- if (pci_domain_nr(pci_dev->bus))
- r = -ENOSYS;
#ifdef CONFIG_PCI_IOV
- else if (pci_dev->is_virtfn) {
+ if (pci_dev->is_virtfn) {
struct physdev_manage_pci_ext manage_pci_ext = {
.bus = pci_dev->bus->number,
.devfn = pci_dev->devfn,
.is_virtfn = 1,
- .physfn.bus = physfn->bus->number,
- .physfn.devfn = physfn->devfn,
+ .physfn.bus = pci_dev->physfn->bus->number,
+ .physfn.devfn = pci_dev->physfn->devfn,
};
r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_add_ext,
&manage_pci_ext);
- }
+ } else
#endif
- else if (pci_ari_enabled(pci_dev->bus) && PCI_SLOT(pci_dev->devfn)) {
+ if (pci_ari_enabled(pci_dev->bus) && PCI_SLOT(pci_dev->devfn)) {
struct physdev_manage_pci_ext manage_pci_ext = {
.bus = pci_dev->bus->number,
.devfn = pci_dev->devfn,
@@ -116,7 +56,7 @@ static int xen_add_device(struct device *dev)
&manage_pci_ext);
} else {
struct physdev_manage_pci manage_pci = {
- .bus = pci_dev->bus->number,
+ .bus = pci_dev->bus->number,
.devfn = pci_dev->devfn,
};
@@ -131,27 +71,13 @@ static int xen_remove_device(struct device *dev)
{
int r;
struct pci_dev *pci_dev = to_pci_dev(dev);
+ struct physdev_manage_pci manage_pci;
- if (pci_seg_supported) {
- struct physdev_pci_device device = {
- .seg = pci_domain_nr(pci_dev->bus),
- .bus = pci_dev->bus->number,
- .devfn = pci_dev->devfn
- };
+ manage_pci.bus = pci_dev->bus->number;
+ manage_pci.devfn = pci_dev->devfn;
- r = HYPERVISOR_physdev_op(PHYSDEVOP_pci_device_remove,
- &device);
- } else if (pci_domain_nr(pci_dev->bus))
- r = -ENOSYS;
- else {
- struct physdev_manage_pci manage_pci = {
- .bus = pci_dev->bus->number,
- .devfn = pci_dev->devfn
- };
-
- r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_remove,
- &manage_pci);
- }
+ r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_remove,
+ &manage_pci);
return r;
}
@@ -170,16 +96,13 @@ static int xen_pci_notifier(struct notifier_block *nb,
r = xen_remove_device(dev);
break;
default:
- return NOTIFY_DONE;
+ break;
}
- if (r)
- dev_err(dev, "Failed to %s - passthrough or MSI/MSI-X might fail!\n",
- action == BUS_NOTIFY_ADD_DEVICE ? "add" :
- (action == BUS_NOTIFY_DEL_DEVICE ? "delete" : "?"));
- return NOTIFY_OK;
+
+ return r;
}
-static struct notifier_block device_nb = {
+struct notifier_block device_nb = {
.notifier_call = xen_pci_notifier,
};
diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c
index 89588e7..fd60dff 100644
--- a/drivers/xen/swiotlb-xen.c
+++ b/drivers/xen/swiotlb-xen.c
@@ -35,11 +35,9 @@
#include <linux/bootmem.h>
#include <linux/dma-mapping.h>
-#include <linux/export.h>
#include <xen/swiotlb-xen.h>
#include <xen/page.h>
#include <xen/xen-ops.h>
-#include <xen/hvc-console.h>
/*
* Used to do a quick range check in swiotlb_tbl_unmap_single and
* swiotlb_tbl_sync_single_*, to see if the memory was in fact allocated by this
@@ -148,10 +146,8 @@ xen_swiotlb_fixup(void *buf, size_t size, unsigned long nslabs)
void __init xen_swiotlb_init(int verbose)
{
unsigned long bytes;
- int rc = -ENOMEM;
+ int rc;
unsigned long nr_tbl;
- char *m = NULL;
- unsigned int repeat = 3;
nr_tbl = swioltb_nr_tbl();
if (nr_tbl)
@@ -160,17 +156,16 @@ void __init xen_swiotlb_init(int verbose)
xen_io_tlb_nslabs = (64 * 1024 * 1024 >> IO_TLB_SHIFT);
xen_io_tlb_nslabs = ALIGN(xen_io_tlb_nslabs, IO_TLB_SEGSIZE);
}
-retry:
+
bytes = xen_io_tlb_nslabs << IO_TLB_SHIFT;
/*
* Get IO TLB memory from any location.
*/
xen_io_tlb_start = alloc_bootmem_pages(PAGE_ALIGN(bytes));
- if (!xen_io_tlb_start) {
- m = "Cannot allocate Xen-SWIOTLB buffer!\n";
- goto error;
- }
+ if (!xen_io_tlb_start)
+ panic("Cannot allocate SWIOTLB buffer");
+
xen_io_tlb_end = xen_io_tlb_start + bytes;
/*
* And replace that memory with pages under 4GB.
@@ -178,28 +173,17 @@ retry:
rc = xen_swiotlb_fixup(xen_io_tlb_start,
bytes,
xen_io_tlb_nslabs);
- if (rc) {
- free_bootmem(__pa(xen_io_tlb_start), PAGE_ALIGN(bytes));
- m = "Failed to get contiguous memory for DMA from Xen!\n"\
- "You either: don't have the permissions, do not have"\
- " enough free memory under 4GB, or the hypervisor memory"\
- "is too fragmented!";
+ if (rc)
goto error;
- }
+
start_dma_addr = xen_virt_to_bus(xen_io_tlb_start);
swiotlb_init_with_tbl(xen_io_tlb_start, xen_io_tlb_nslabs, verbose);
return;
error:
- if (repeat--) {
- xen_io_tlb_nslabs = max(1024UL, /* Min is 2MB */
- (xen_io_tlb_nslabs >> 1));
- printk(KERN_INFO "Xen-SWIOTLB: Lowering to %luMB\n",
- (xen_io_tlb_nslabs << IO_TLB_SHIFT) >> 20);
- goto retry;
- }
- xen_raw_printk("%s (rc:%d)", m, rc);
- panic("%s (rc:%d)", m, rc);
+ panic("DMA(%d): Failed to exchange pages allocated for DMA with Xen! "\
+ "We either don't have the permission or you do not have enough"\
+ "free memory under 4GB!\n", rc);
}
void *
@@ -210,8 +194,6 @@ xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
int order = get_order(size);
u64 dma_mask = DMA_BIT_MASK(32);
unsigned long vstart;
- phys_addr_t phys;
- dma_addr_t dev_addr;
/*
* Ignore region specifiers - the kernel's ideas of
@@ -227,26 +209,18 @@ xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
vstart = __get_free_pages(flags, order);
ret = (void *)vstart;
- if (!ret)
- return ret;
-
if (hwdev && hwdev->coherent_dma_mask)
dma_mask = dma_alloc_coherent_mask(hwdev, flags);
- phys = virt_to_phys(ret);
- dev_addr = xen_phys_to_bus(phys);
- if (((dev_addr + size - 1 <= dma_mask)) &&
- !range_straddles_page_boundary(phys, size))
- *dma_handle = dev_addr;
- else {
+ if (ret) {
if (xen_create_contiguous_region(vstart, order,
fls64(dma_mask)) != 0) {
free_pages(vstart, order);
return NULL;
}
+ memset(ret, 0, size);
*dma_handle = virt_to_machine(ret).maddr;
}
- memset(ret, 0, size);
return ret;
}
EXPORT_SYMBOL_GPL(xen_swiotlb_alloc_coherent);
@@ -256,21 +230,11 @@ xen_swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr,
dma_addr_t dev_addr)
{
int order = get_order(size);
- phys_addr_t phys;
- u64 dma_mask = DMA_BIT_MASK(32);
if (dma_release_from_coherent(hwdev, order, vaddr))
return;
- if (hwdev && hwdev->coherent_dma_mask)
- dma_mask = hwdev->coherent_dma_mask;
-
- phys = virt_to_phys(vaddr);
-
- if (((dev_addr + size - 1 > dma_mask)) ||
- range_straddles_page_boundary(phys, size))
- xen_destroy_contiguous_region((unsigned long)vaddr, order);
-
+ xen_destroy_contiguous_region((unsigned long)vaddr, order);
free_pages((unsigned long)vaddr, order);
}
EXPORT_SYMBOL_GPL(xen_swiotlb_free_coherent);
diff --git a/drivers/xen/tmem.c b/drivers/xen/tmem.c
index d369965..816a449 100644
--- a/drivers/xen/tmem.c
+++ b/drivers/xen/tmem.c
@@ -1,7 +1,7 @@
/*
* Xen implementation for transcendent memory (tmem)
*
- * Copyright (C) 2009-2011 Oracle Corp. All rights reserved.
+ * Copyright (C) 2009-2010 Oracle Corp. All rights reserved.
* Author: Dan Magenheimer
*/
@@ -9,14 +9,8 @@
#include <linux/types.h>
#include <linux/init.h>
#include <linux/pagemap.h>
-#include <linux/module.h>
#include <linux/cleancache.h>
-/* temporary ifdef until include/linux/frontswap.h is upstream */
-#ifdef CONFIG_FRONTSWAP
-#include <linux/frontswap.h>
-#endif
-
#include <xen/xen.h>
#include <xen/interface/xen.h>
#include <asm/xen/hypercall.h>
@@ -128,8 +122,14 @@ static int xen_tmem_flush_object(u32 pool_id, struct tmem_oid oid)
return xen_tmem_op(TMEM_FLUSH_OBJECT, pool_id, oid, 0, 0, 0, 0, 0);
}
-int tmem_enabled __read_mostly;
-EXPORT_SYMBOL(tmem_enabled);
+static int xen_tmem_destroy_pool(u32 pool_id)
+{
+ struct tmem_oid oid = { { 0 } };
+
+ return xen_tmem_op(TMEM_DESTROY_POOL, pool_id, oid, 0, 0, 0, 0, 0);
+}
+
+int tmem_enabled;
static int __init enable_tmem(char *s)
{
@@ -139,14 +139,6 @@ static int __init enable_tmem(char *s)
__setup("tmem", enable_tmem);
-#ifdef CONFIG_CLEANCACHE
-static int xen_tmem_destroy_pool(u32 pool_id)
-{
- struct tmem_oid oid = { { 0 } };
-
- return xen_tmem_op(TMEM_DESTROY_POOL, pool_id, oid, 0, 0, 0, 0, 0);
-}
-
/* cleancache ops */
static void tmem_cleancache_put_page(int pool, struct cleancache_filekey key,
@@ -248,156 +240,18 @@ static struct cleancache_ops tmem_cleancache_ops = {
.init_shared_fs = tmem_cleancache_init_shared_fs,
.init_fs = tmem_cleancache_init_fs
};
-#endif
-
-#ifdef CONFIG_FRONTSWAP
-/* frontswap tmem operations */
-
-/* a single tmem poolid is used for all frontswap "types" (swapfiles) */
-static int tmem_frontswap_poolid;
-
-/*
- * Swizzling increases objects per swaptype, increasing tmem concurrency
- * for heavy swaploads. Later, larger nr_cpus -> larger SWIZ_BITS
- */
-#define SWIZ_BITS 4
-#define SWIZ_MASK ((1 << SWIZ_BITS) - 1)
-#define _oswiz(_type, _ind) ((_type << SWIZ_BITS) | (_ind & SWIZ_MASK))
-#define iswiz(_ind) (_ind >> SWIZ_BITS)
-
-static inline struct tmem_oid oswiz(unsigned type, u32 ind)
-{
- struct tmem_oid oid = { .oid = { 0 } };
- oid.oid[0] = _oswiz(type, ind);
- return oid;
-}
-
-/* returns 0 if the page was successfully put into frontswap, -1 if not */
-static int tmem_frontswap_put_page(unsigned type, pgoff_t offset,
- struct page *page)
-{
- u64 ind64 = (u64)offset;
- u32 ind = (u32)offset;
- unsigned long pfn = page_to_pfn(page);
- int pool = tmem_frontswap_poolid;
- int ret;
-
- if (pool < 0)
- return -1;
- if (ind64 != ind)
- return -1;
- mb(); /* ensure page is quiescent; tmem may address it with an alias */
- ret = xen_tmem_put_page(pool, oswiz(type, ind), iswiz(ind), pfn);
- /* translate Xen tmem return values to linux semantics */
- if (ret == 1)
- return 0;
- else
- return -1;
-}
-
-/*
- * returns 0 if the page was successfully gotten from frontswap, -1 if
- * was not present (should never happen!)
- */
-static int tmem_frontswap_get_page(unsigned type, pgoff_t offset,
- struct page *page)
-{
- u64 ind64 = (u64)offset;
- u32 ind = (u32)offset;
- unsigned long pfn = page_to_pfn(page);
- int pool = tmem_frontswap_poolid;
- int ret;
-
- if (pool < 0)
- return -1;
- if (ind64 != ind)
- return -1;
- ret = xen_tmem_get_page(pool, oswiz(type, ind), iswiz(ind), pfn);
- /* translate Xen tmem return values to linux semantics */
- if (ret == 1)
- return 0;
- else
- return -1;
-}
-
-/* flush a single page from frontswap */
-static void tmem_frontswap_flush_page(unsigned type, pgoff_t offset)
-{
- u64 ind64 = (u64)offset;
- u32 ind = (u32)offset;
- int pool = tmem_frontswap_poolid;
-
- if (pool < 0)
- return;
- if (ind64 != ind)
- return;
- (void) xen_tmem_flush_page(pool, oswiz(type, ind), iswiz(ind));
-}
-
-/* flush all pages from the passed swaptype */
-static void tmem_frontswap_flush_area(unsigned type)
-{
- int pool = tmem_frontswap_poolid;
- int ind;
-
- if (pool < 0)
- return;
- for (ind = SWIZ_MASK; ind >= 0; ind--)
- (void)xen_tmem_flush_object(pool, oswiz(type, ind));
-}
-
-static void tmem_frontswap_init(unsigned ignored)
-{
- struct tmem_pool_uuid private = TMEM_POOL_PRIVATE_UUID;
-
- /* a single tmem poolid is used for all frontswap "types" (swapfiles) */
- if (tmem_frontswap_poolid < 0)
- tmem_frontswap_poolid =
- xen_tmem_new_pool(private, TMEM_POOL_PERSIST, PAGE_SIZE);
-}
-
-static int __initdata use_frontswap = 1;
-
-static int __init no_frontswap(char *s)
-{
- use_frontswap = 0;
- return 1;
-}
-
-__setup("nofrontswap", no_frontswap);
-
-static struct frontswap_ops tmem_frontswap_ops = {
- .put_page = tmem_frontswap_put_page,
- .get_page = tmem_frontswap_get_page,
- .flush_page = tmem_frontswap_flush_page,
- .flush_area = tmem_frontswap_flush_area,
- .init = tmem_frontswap_init
-};
-#endif
static int __init xen_tmem_init(void)
{
+ struct cleancache_ops old_ops;
+
if (!xen_domain())
return 0;
-#ifdef CONFIG_FRONTSWAP
- if (tmem_enabled && use_frontswap) {
- char *s = "";
- struct frontswap_ops old_ops =
- frontswap_register_ops(&tmem_frontswap_ops);
-
- tmem_frontswap_poolid = -1;
- if (old_ops.init != NULL)
- s = " (WARNING: frontswap_ops overridden)";
- printk(KERN_INFO "frontswap enabled, RAM provided by "
- "Xen Transcendent Memory\n");
- }
-#endif
#ifdef CONFIG_CLEANCACHE
BUG_ON(sizeof(struct cleancache_filekey) != sizeof(struct tmem_oid));
if (tmem_enabled && use_cleancache) {
char *s = "";
- struct cleancache_ops old_ops =
- cleancache_register_ops(&tmem_cleancache_ops);
+ old_ops = cleancache_register_ops(&tmem_cleancache_ops);
if (old_ops.init_fs != NULL)
s = " (WARNING: cleancache_ops overridden)";
printk(KERN_INFO "cleancache enabled, RAM provided by "
diff --git a/drivers/xen/xen-balloon.c b/drivers/xen/xen-balloon.c
index 9cc2259..a4ff225 100644
--- a/drivers/xen/xen-balloon.c
+++ b/drivers/xen/xen-balloon.c
@@ -50,6 +50,11 @@ static struct sys_device balloon_sysdev;
static int register_balloon(struct sys_device *sysdev);
+static struct xenbus_watch target_watch =
+{
+ .node = "memory/target"
+};
+
/* React to a change in the target key */
static void watch_target(struct xenbus_watch *watch,
const char **vec, unsigned int len)
@@ -68,11 +73,6 @@ static void watch_target(struct xenbus_watch *watch,
*/
balloon_set_new_target(new_target >> (PAGE_SHIFT - 10));
}
-static struct xenbus_watch target_watch = {
- .node = "memory/target",
- .callback = watch_target,
-};
-
static int balloon_init_watcher(struct notifier_block *notifier,
unsigned long event,
@@ -87,9 +87,7 @@ static int balloon_init_watcher(struct notifier_block *notifier,
return NOTIFY_DONE;
}
-static struct notifier_block xenstore_notifier = {
- .notifier_call = balloon_init_watcher,
-};
+static struct notifier_block xenstore_notifier;
static int __init balloon_init(void)
{
@@ -100,7 +98,8 @@ static int __init balloon_init(void)
register_balloon(&balloon_sysdev);
- register_xen_selfballooning(&balloon_sysdev);
+ target_watch.callback = watch_target;
+ xenstore_notifier.notifier_call = balloon_init_watcher;
register_xenstore_notifier(&xenstore_notifier);
diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c
index 1906125..cdacf92 100644
--- a/drivers/xen/xenbus/xenbus_client.c
+++ b/drivers/xen/xenbus/xenbus_client.c
@@ -33,9 +33,7 @@
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/vmalloc.h>
-#include <linux/export.h>
#include <asm/xen/hypervisor.h>
-#include <asm/xen/page.h>
#include <xen/interface/xen.h>
#include <xen/interface/event_channel.h>
#include <xen/events.h>
@@ -437,26 +435,25 @@ EXPORT_SYMBOL_GPL(xenbus_free_evtchn);
int xenbus_map_ring_valloc(struct xenbus_device *dev, int gnt_ref, void **vaddr)
{
struct gnttab_map_grant_ref op = {
- .flags = GNTMAP_host_map | GNTMAP_contains_pte,
+ .flags = GNTMAP_host_map,
.ref = gnt_ref,
.dom = dev->otherend_id,
};
struct vm_struct *area;
- pte_t *pte;
*vaddr = NULL;
- area = alloc_vm_area(PAGE_SIZE, &pte);
+ area = xen_alloc_vm_area(PAGE_SIZE);
if (!area)
return -ENOMEM;
- op.host_addr = arbitrary_virt_to_machine(pte).maddr;
+ op.host_addr = (unsigned long)area->addr;
if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
BUG();
if (op.status != GNTST_okay) {
- free_vm_area(area);
+ xen_free_vm_area(area);
xenbus_dev_fatal(dev, op.status,
"mapping in shared page %d from domain %d",
gnt_ref, dev->otherend_id);
@@ -529,7 +526,6 @@ int xenbus_unmap_ring_vfree(struct xenbus_device *dev, void *vaddr)
struct gnttab_unmap_grant_ref op = {
.host_addr = (unsigned long)vaddr,
};
- unsigned int level;
/* It'd be nice if linux/vmalloc.h provided a find_vm_area(void *addr)
* method so that we don't have to muck with vmalloc internals here.
@@ -551,14 +547,12 @@ int xenbus_unmap_ring_vfree(struct xenbus_device *dev, void *vaddr)
}
op.handle = (grant_handle_t)area->phys_addr;
- op.host_addr = arbitrary_virt_to_machine(
- lookup_address((unsigned long)vaddr, &level)).maddr;
if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1))
BUG();
if (op.status == GNTST_okay)
- free_vm_area(area);
+ xen_free_vm_area(area);
else
xenbus_dev_error(dev, op.status,
"unmapping page at handle %d error %d",
diff --git a/drivers/xen/xenbus/xenbus_comms.c b/drivers/xen/xenbus/xenbus_comms.c
index 2eff7a6..090c61e 100644
--- a/drivers/xen/xenbus/xenbus_comms.c
+++ b/drivers/xen/xenbus/xenbus_comms.c
@@ -212,9 +212,7 @@ int xb_init_comms(void)
printk(KERN_WARNING "XENBUS response ring is not quiescent "
"(%08x:%08x): fixing up\n",
intf->rsp_cons, intf->rsp_prod);
- /* breaks kdump */
- if (!reset_devices)
- intf->rsp_cons = intf->rsp_prod;
+ intf->rsp_cons = intf->rsp_prod;
}
if (xenbus_irq) {
diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c
index 1b178c6..7397695 100644
--- a/drivers/xen/xenbus/xenbus_probe.c
+++ b/drivers/xen/xenbus/xenbus_probe.c
@@ -46,7 +46,6 @@
#include <linux/mutex.h>
#include <linux/io.h>
#include <linux/slab.h>
-#include <linux/module.h>
#include <asm/page.h>
#include <asm/pgtable.h>
@@ -310,7 +309,8 @@ void xenbus_unregister_driver(struct xenbus_driver *drv)
}
EXPORT_SYMBOL_GPL(xenbus_unregister_driver);
-struct xb_find_info {
+struct xb_find_info
+{
struct xenbus_device *dev;
const char *nodename;
};
@@ -378,32 +378,26 @@ static void xenbus_dev_release(struct device *dev)
kfree(to_xenbus_device(dev));
}
-static ssize_t nodename_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t xendev_show_nodename(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%s\n", to_xenbus_device(dev)->nodename);
}
+static DEVICE_ATTR(nodename, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_nodename, NULL);
-static ssize_t devtype_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t xendev_show_devtype(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%s\n", to_xenbus_device(dev)->devicetype);
}
+static DEVICE_ATTR(devtype, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_devtype, NULL);
-static ssize_t modalias_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t xendev_show_modalias(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
- return sprintf(buf, "%s:%s\n", dev->bus->name,
- to_xenbus_device(dev)->devicetype);
+ return sprintf(buf, "xen:%s\n", to_xenbus_device(dev)->devicetype);
}
-
-struct device_attribute xenbus_dev_attrs[] = {
- __ATTR_RO(nodename),
- __ATTR_RO(devtype),
- __ATTR_RO(modalias),
- __ATTR_NULL
-};
-EXPORT_SYMBOL_GPL(xenbus_dev_attrs);
+static DEVICE_ATTR(modalias, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_modalias, NULL);
int xenbus_probe_node(struct xen_bus_type *bus,
const char *type,
@@ -455,7 +449,25 @@ int xenbus_probe_node(struct xen_bus_type *bus,
if (err)
goto fail;
+ err = device_create_file(&xendev->dev, &dev_attr_nodename);
+ if (err)
+ goto fail_unregister;
+
+ err = device_create_file(&xendev->dev, &dev_attr_devtype);
+ if (err)
+ goto fail_remove_nodename;
+
+ err = device_create_file(&xendev->dev, &dev_attr_modalias);
+ if (err)
+ goto fail_remove_devtype;
+
return 0;
+fail_remove_devtype:
+ device_remove_file(&xendev->dev, &dev_attr_devtype);
+fail_remove_nodename:
+ device_remove_file(&xendev->dev, &dev_attr_nodename);
+fail_unregister:
+ device_unregister(&xendev->dev);
fail:
kfree(xendev);
return err;
@@ -639,7 +651,7 @@ int xenbus_dev_cancel(struct device *dev)
EXPORT_SYMBOL_GPL(xenbus_dev_cancel);
/* A flag to determine if xenstored is 'ready' (i.e. has started) */
-int xenstored_ready;
+int xenstored_ready = 0;
int register_xenstore_notifier(struct notifier_block *nb)
@@ -684,74 +696,64 @@ static int __init xenbus_probe_initcall(void)
device_initcall(xenbus_probe_initcall);
-/* Set up event channel for xenstored which is run as a local process
- * (this is normally used only in dom0)
- */
-static int __init xenstored_local_init(void)
+static int __init xenbus_init(void)
{
int err = 0;
unsigned long page = 0;
- struct evtchn_alloc_unbound alloc_unbound;
- /* Allocate Xenstore page */
- page = get_zeroed_page(GFP_KERNEL);
- if (!page)
- goto out_err;
+ DPRINTK("");
- xen_store_mfn = xen_start_info->store_mfn =
- pfn_to_mfn(virt_to_phys((void *)page) >>
- PAGE_SHIFT);
+ err = -ENODEV;
+ if (!xen_domain())
+ return err;
- /* Next allocate a local port which xenstored can bind to */
- alloc_unbound.dom = DOMID_SELF;
- alloc_unbound.remote_dom = DOMID_SELF;
+ /*
+ * Domain0 doesn't have a store_evtchn or store_mfn yet.
+ */
+ if (xen_initial_domain()) {
+ struct evtchn_alloc_unbound alloc_unbound;
- err = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound,
- &alloc_unbound);
- if (err == -ENOSYS)
- goto out_err;
+ /* Allocate Xenstore page */
+ page = get_zeroed_page(GFP_KERNEL);
+ if (!page)
+ goto out_error;
- BUG_ON(err);
- xen_store_evtchn = xen_start_info->store_evtchn =
- alloc_unbound.port;
+ xen_store_mfn = xen_start_info->store_mfn =
+ pfn_to_mfn(virt_to_phys((void *)page) >>
+ PAGE_SHIFT);
- return 0;
-
- out_err:
- if (page != 0)
- free_page(page);
- return err;
-}
+ /* Next allocate a local port which xenstored can bind to */
+ alloc_unbound.dom = DOMID_SELF;
+ alloc_unbound.remote_dom = 0;
-static int __init xenbus_init(void)
-{
- int err = 0;
+ err = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound,
+ &alloc_unbound);
+ if (err == -ENOSYS)
+ goto out_error;
- if (!xen_domain())
- return -ENODEV;
+ BUG_ON(err);
+ xen_store_evtchn = xen_start_info->store_evtchn =
+ alloc_unbound.port;
- if (xen_hvm_domain()) {
- uint64_t v = 0;
- err = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v);
- if (err)
- goto out_error;
- xen_store_evtchn = (int)v;
- err = hvm_get_parameter(HVM_PARAM_STORE_PFN, &v);
- if (err)
- goto out_error;
- xen_store_mfn = (unsigned long)v;
- xen_store_interface = ioremap(xen_store_mfn << PAGE_SHIFT, PAGE_SIZE);
+ xen_store_interface = mfn_to_virt(xen_store_mfn);
} else {
- xen_store_evtchn = xen_start_info->store_evtchn;
- xen_store_mfn = xen_start_info->store_mfn;
- if (xen_store_evtchn)
- xenstored_ready = 1;
- else {
- err = xenstored_local_init();
+ if (xen_hvm_domain()) {
+ uint64_t v = 0;
+ err = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v);
+ if (err)
+ goto out_error;
+ xen_store_evtchn = (int)v;
+ err = hvm_get_parameter(HVM_PARAM_STORE_PFN, &v);
if (err)
goto out_error;
+ xen_store_mfn = (unsigned long)v;
+ xen_store_interface = ioremap(xen_store_mfn << PAGE_SHIFT, PAGE_SIZE);
+ } else {
+ xen_store_evtchn = xen_start_info->store_evtchn;
+ xen_store_mfn = xen_start_info->store_mfn;
+ xen_store_interface = mfn_to_virt(xen_store_mfn);
+ xenstored_ready = 1;
}
- xen_store_interface = mfn_to_virt(xen_store_mfn);
}
/* Initialize the interface to xenstore. */
@@ -770,7 +772,12 @@ static int __init xenbus_init(void)
proc_mkdir("xen", NULL);
#endif
-out_error:
+ return 0;
+
+ out_error:
+ if (page != 0)
+ free_page(page);
+
return err;
}
diff --git a/drivers/xen/xenbus/xenbus_probe.h b/drivers/xen/xenbus/xenbus_probe.h
index 9b1de4e..888b990 100644
--- a/drivers/xen/xenbus/xenbus_probe.h
+++ b/drivers/xen/xenbus/xenbus_probe.h
@@ -36,7 +36,8 @@
#define XEN_BUS_ID_SIZE 20
-struct xen_bus_type {
+struct xen_bus_type
+{
char *root;
unsigned int levels;
int (*get_bus_id)(char bus_id[XEN_BUS_ID_SIZE], const char *nodename);
@@ -47,8 +48,6 @@ struct xen_bus_type {
struct bus_type bus;
};
-extern struct device_attribute xenbus_dev_attrs[];
-
extern int xenbus_match(struct device *_dev, struct device_driver *_drv);
extern int xenbus_dev_probe(struct device *_dev);
extern int xenbus_dev_remove(struct device *_dev);
diff --git a/drivers/xen/xenbus/xenbus_probe_backend.c b/drivers/xen/xenbus/xenbus_probe_backend.c
index c3c7cd1..6cf467b 100644
--- a/drivers/xen/xenbus/xenbus_probe_backend.c
+++ b/drivers/xen/xenbus/xenbus_probe_backend.c
@@ -42,7 +42,6 @@
#include <linux/fcntl.h>
#include <linux/mm.h>
#include <linux/notifier.h>
-#include <linux/export.h>
#include <asm/page.h>
#include <asm/pgtable.h>
@@ -105,9 +104,8 @@ static int xenbus_uevent_backend(struct device *dev,
xdev = to_xenbus_device(dev);
bus = container_of(xdev->dev.bus, struct xen_bus_type, bus);
-
- if (add_uevent_var(env, "MODALIAS=xen-backend:%s", xdev->devicetype))
- return -ENOMEM;
+ if (xdev == NULL)
+ return -ENODEV;
/* stuff we want to pass to /sbin/hotplug */
if (add_uevent_var(env, "XENBUS_TYPE=%s", xdev->devicetype))
@@ -185,6 +183,10 @@ static void frontend_changed(struct xenbus_watch *watch,
xenbus_otherend_changed(watch, vec, len, 0);
}
+static struct device_attribute xenbus_backend_dev_attrs[] = {
+ __ATTR_NULL
+};
+
static struct xen_bus_type xenbus_backend = {
.root = "backend",
.levels = 3, /* backend/type/<frontend>/<id> */
@@ -198,7 +200,7 @@ static struct xen_bus_type xenbus_backend = {
.probe = xenbus_dev_probe,
.remove = xenbus_dev_remove,
.shutdown = xenbus_dev_shutdown,
- .dev_attrs = xenbus_dev_attrs,
+ .dev_attrs = xenbus_backend_dev_attrs,
},
};
diff --git a/drivers/xen/xenbus/xenbus_probe_frontend.c b/drivers/xen/xenbus/xenbus_probe_frontend.c
index 2ce95c0..560f217 100644
--- a/drivers/xen/xenbus/xenbus_probe_frontend.c
+++ b/drivers/xen/xenbus/xenbus_probe_frontend.c
@@ -13,7 +13,6 @@
#include <linux/kthread.h>
#include <linux/mutex.h>
#include <linux/io.h>
-#include <linux/module.h>
#include <asm/page.h>
#include <asm/pgtable.h>
@@ -82,6 +81,10 @@ static void backend_changed(struct xenbus_watch *watch,
xenbus_otherend_changed(watch, vec, len, 1);
}
+static struct device_attribute xenbus_frontend_dev_attrs[] = {
+ __ATTR_NULL
+};
+
static const struct dev_pm_ops xenbus_pm_ops = {
.suspend = xenbus_dev_suspend,
.resume = xenbus_dev_resume,
@@ -103,7 +106,7 @@ static struct xen_bus_type xenbus_frontend = {
.probe = xenbus_dev_probe,
.remove = xenbus_dev_remove,
.shutdown = xenbus_dev_shutdown,
- .dev_attrs = xenbus_dev_attrs,
+ .dev_attrs = xenbus_frontend_dev_attrs,
.pm = &xenbus_pm_ops,
},
@@ -286,131 +289,10 @@ int __xenbus_register_frontend(struct xenbus_driver *drv,
}
EXPORT_SYMBOL_GPL(__xenbus_register_frontend);
-static DECLARE_WAIT_QUEUE_HEAD(backend_state_wq);
-static int backend_state;
-
-static void xenbus_reset_backend_state_changed(struct xenbus_watch *w,
- const char **v, unsigned int l)
-{
- xenbus_scanf(XBT_NIL, v[XS_WATCH_PATH], "", "%i", &backend_state);
- printk(KERN_DEBUG "XENBUS: backend %s %s\n",
- v[XS_WATCH_PATH], xenbus_strstate(backend_state));
- wake_up(&backend_state_wq);
-}
-
-static void xenbus_reset_wait_for_backend(char *be, int expected)
-{
- long timeout;
- timeout = wait_event_interruptible_timeout(backend_state_wq,
- backend_state == expected, 5 * HZ);
- if (timeout <= 0)
- printk(KERN_INFO "XENBUS: backend %s timed out.\n", be);
-}
-
-/*
- * Reset frontend if it is in Connected or Closed state.
- * Wait for backend to catch up.
- * State Connected happens during kdump, Closed after kexec.
- */
-static void xenbus_reset_frontend(char *fe, char *be, int be_state)
-{
- struct xenbus_watch be_watch;
-
- printk(KERN_DEBUG "XENBUS: backend %s %s\n",
- be, xenbus_strstate(be_state));
-
- memset(&be_watch, 0, sizeof(be_watch));
- be_watch.node = kasprintf(GFP_NOIO | __GFP_HIGH, "%s/state", be);
- if (!be_watch.node)
- return;
-
- be_watch.callback = xenbus_reset_backend_state_changed;
- backend_state = XenbusStateUnknown;
-
- printk(KERN_INFO "XENBUS: triggering reconnect on %s\n", be);
- register_xenbus_watch(&be_watch);
-
- /* fall through to forward backend to state XenbusStateInitialising */
- switch (be_state) {
- case XenbusStateConnected:
- xenbus_printf(XBT_NIL, fe, "state", "%d", XenbusStateClosing);
- xenbus_reset_wait_for_backend(be, XenbusStateClosing);
-
- case XenbusStateClosing:
- xenbus_printf(XBT_NIL, fe, "state", "%d", XenbusStateClosed);
- xenbus_reset_wait_for_backend(be, XenbusStateClosed);
-
- case XenbusStateClosed:
- xenbus_printf(XBT_NIL, fe, "state", "%d", XenbusStateInitialising);
- xenbus_reset_wait_for_backend(be, XenbusStateInitWait);
- }
-
- unregister_xenbus_watch(&be_watch);
- printk(KERN_INFO "XENBUS: reconnect done on %s\n", be);
- kfree(be_watch.node);
-}
-
-static void xenbus_check_frontend(char *class, char *dev)
-{
- int be_state, fe_state, err;
- char *backend, *frontend;
-
- frontend = kasprintf(GFP_NOIO | __GFP_HIGH, "device/%s/%s", class, dev);
- if (!frontend)
- return;
-
- err = xenbus_scanf(XBT_NIL, frontend, "state", "%i", &fe_state);
- if (err != 1)
- goto out;
-
- switch (fe_state) {
- case XenbusStateConnected:
- case XenbusStateClosed:
- printk(KERN_DEBUG "XENBUS: frontend %s %s\n",
- frontend, xenbus_strstate(fe_state));
- backend = xenbus_read(XBT_NIL, frontend, "backend", NULL);
- if (!backend || IS_ERR(backend))
- goto out;
- err = xenbus_scanf(XBT_NIL, backend, "state", "%i", &be_state);
- if (err == 1)
- xenbus_reset_frontend(frontend, backend, be_state);
- kfree(backend);
- break;
- default:
- break;
- }
-out:
- kfree(frontend);
-}
-
-static void xenbus_reset_state(void)
-{
- char **devclass, **dev;
- int devclass_n, dev_n;
- int i, j;
-
- devclass = xenbus_directory(XBT_NIL, "device", "", &devclass_n);
- if (IS_ERR(devclass))
- return;
-
- for (i = 0; i < devclass_n; i++) {
- dev = xenbus_directory(XBT_NIL, "device", devclass[i], &dev_n);
- if (IS_ERR(dev))
- continue;
- for (j = 0; j < dev_n; j++)
- xenbus_check_frontend(devclass[i], dev[j]);
- kfree(dev);
- }
- kfree(devclass);
-}
-
static int frontend_probe_and_watch(struct notifier_block *notifier,
unsigned long event,
void *data)
{
- /* reset devices in Connected or Closed state */
- if (xen_hvm_domain())
- xenbus_reset_state();
/* Enumerate devices in xenstore and watch for changes. */
xenbus_probe_devices(&xenbus_frontend);
register_xenbus_watch(&fe_watch);
diff --git a/drivers/xen/xenbus/xenbus_xs.c b/drivers/xen/xenbus/xenbus_xs.c
index a580b17..daee5db 100644
--- a/drivers/xen/xenbus/xenbus_xs.c
+++ b/drivers/xen/xenbus/xenbus_xs.c
@@ -45,7 +45,6 @@
#include <linux/module.h>
#include <linux/mutex.h>
#include <xen/xenbus.h>
-#include <xen/xen.h>
#include "xenbus_comms.h"
struct xs_stored_msg {
@@ -639,7 +638,8 @@ int register_xenbus_watch(struct xenbus_watch *watch)
err = xs_watch(watch->node, token);
- if (err) {
+ /* Ignore errors due to multiple registration. */
+ if ((err != 0) && (err != -EEXIST)) {
spin_lock(&watches_lock);
list_del(&watch->list);
spin_unlock(&watches_lock);