Commit 3655b22d authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'stable/for-linus-3.10-rc3-tag' of...

Merge tag 'stable/for-linus-3.10-rc3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen

Pull Xen fixes from Konrad Rzeszutek Wilk:
 - Use proper error paths
 - Clean up APIC IPI usage (incorrect arguments)
 - Delay XenBus frontend resume is backend (xenstored) is not running
 - Fix build error with various combinations of CONFIG_

* tag 'stable/for-linus-3.10-rc3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen:
  xenbus_client.c: correct exit path for xenbus_map_ring_valloc_hvm
  xen-pciback: more uses of cached MSI-X capability offset
  xen: Clean up apic ipi interface
  xenbus: save xenstore local status for later use
  xenbus: delay xenbus frontend resume if xenstored is not running
  xmem/tmem: fix 'undefined variable' build error.
parents 5489e948 8d0b8801
......@@ -576,24 +576,22 @@ void xen_send_IPI_mask_allbutself(const struct cpumask *mask,
{
unsigned cpu;
unsigned int this_cpu = smp_processor_id();
int xen_vector = xen_map_vector(vector);
if (!(num_online_cpus() > 1))
if (!(num_online_cpus() > 1) || (xen_vector < 0))
return;
for_each_cpu_and(cpu, mask, cpu_online_mask) {
if (this_cpu == cpu)
continue;
xen_smp_send_call_function_single_ipi(cpu);
xen_send_IPI_one(cpu, xen_vector);
}
}
void xen_send_IPI_allbutself(int vector)
{
int xen_vector = xen_map_vector(vector);
if (xen_vector >= 0)
xen_send_IPI_mask_allbutself(cpu_online_mask, xen_vector);
xen_send_IPI_mask_allbutself(cpu_online_mask, vector);
}
static irqreturn_t xen_call_function_interrupt(int irq, void *dev_id)
......
......@@ -5,7 +5,6 @@ extern void xen_send_IPI_mask(const struct cpumask *mask,
extern void xen_send_IPI_mask_allbutself(const struct cpumask *mask,
int vector);
extern void xen_send_IPI_allbutself(int vector);
extern void physflat_send_IPI_allbutself(int vector);
extern void xen_send_IPI_all(int vector);
extern void xen_send_IPI_self(int vector);
......
......@@ -41,6 +41,8 @@ module_param(selfballooning, bool, S_IRUGO);
#ifdef CONFIG_FRONTSWAP
static bool frontswap __read_mostly = true;
module_param(frontswap, bool, S_IRUGO);
#else /* CONFIG_FRONTSWAP */
#define frontswap (0)
#endif /* CONFIG_FRONTSWAP */
#ifdef CONFIG_XEN_SELFBALLOONING
......
......@@ -106,7 +106,7 @@ static void pcistub_device_release(struct kref *kref)
else
pci_restore_state(dev);
if (pci_find_capability(dev, PCI_CAP_ID_MSIX)) {
if (dev->msix_cap) {
struct physdev_pci_device ppdev = {
.seg = pci_domain_nr(dev->bus),
.bus = dev->bus->number,
......@@ -371,7 +371,7 @@ static int pcistub_init_device(struct pci_dev *dev)
if (err)
goto config_release;
if (pci_find_capability(dev, PCI_CAP_ID_MSIX)) {
if (dev->msix_cap) {
struct physdev_pci_device ppdev = {
.seg = pci_domain_nr(dev->bus),
.bus = dev->bus->number,
......
......@@ -534,7 +534,7 @@ static int xenbus_map_ring_valloc_hvm(struct xenbus_device *dev,
err = xenbus_map_ring(dev, gnt_ref, &node->handle, addr);
if (err)
goto out_err;
goto out_err_free_ballooned_pages;
spin_lock(&xenbus_valloc_lock);
list_add(&node->next, &xenbus_valloc_pages);
......@@ -543,8 +543,9 @@ static int xenbus_map_ring_valloc_hvm(struct xenbus_device *dev,
*vaddr = addr;
return 0;
out_err:
out_err_free_ballooned_pages:
free_xenballooned_pages(1, &node->page);
out_err:
kfree(node);
return err;
}
......
......@@ -45,6 +45,7 @@ int xb_wait_for_data_to_read(void);
int xs_input_avail(void);
extern struct xenstore_domain_interface *xen_store_interface;
extern int xen_store_evtchn;
extern enum xenstore_init xen_store_domain_type;
extern const struct file_operations xen_xenbus_fops;
......
......@@ -69,6 +69,9 @@ EXPORT_SYMBOL_GPL(xen_store_evtchn);
struct xenstore_domain_interface *xen_store_interface;
EXPORT_SYMBOL_GPL(xen_store_interface);
enum xenstore_init xen_store_domain_type;
EXPORT_SYMBOL_GPL(xen_store_domain_type);
static unsigned long xen_store_mfn;
static BLOCKING_NOTIFIER_HEAD(xenstore_chain);
......@@ -719,17 +722,11 @@ static int __init xenstored_local_init(void)
return err;
}
enum xenstore_init {
UNKNOWN,
PV,
HVM,
LOCAL,
};
static int __init xenbus_init(void)
{
int err = 0;
enum xenstore_init usage = UNKNOWN;
uint64_t v = 0;
xen_store_domain_type = XS_UNKNOWN;
if (!xen_domain())
return -ENODEV;
......@@ -737,29 +734,29 @@ static int __init xenbus_init(void)
xenbus_ring_ops_init();
if (xen_pv_domain())
usage = PV;
xen_store_domain_type = XS_PV;
if (xen_hvm_domain())
usage = HVM;
xen_store_domain_type = XS_HVM;
if (xen_hvm_domain() && xen_initial_domain())
usage = LOCAL;
xen_store_domain_type = XS_LOCAL;
if (xen_pv_domain() && !xen_start_info->store_evtchn)
usage = LOCAL;
xen_store_domain_type = XS_LOCAL;
if (xen_pv_domain() && xen_start_info->store_evtchn)
xenstored_ready = 1;
switch (usage) {
case LOCAL:
switch (xen_store_domain_type) {
case XS_LOCAL:
err = xenstored_local_init();
if (err)
goto out_error;
xen_store_interface = mfn_to_virt(xen_store_mfn);
break;
case PV:
case XS_PV:
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);
break;
case HVM:
case XS_HVM:
err = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v);
if (err)
goto out_error;
......
......@@ -47,6 +47,13 @@ struct xen_bus_type {
struct bus_type bus;
};
enum xenstore_init {
XS_UNKNOWN,
XS_PV,
XS_HVM,
XS_LOCAL,
};
extern struct device_attribute xenbus_dev_attrs[];
extern int xenbus_match(struct device *_dev, struct device_driver *_drv);
......
......@@ -29,6 +29,8 @@
#include "xenbus_probe.h"
static struct workqueue_struct *xenbus_frontend_wq;
/* device/<type>/<id> => <type>-<id> */
static int frontend_bus_id(char bus_id[XEN_BUS_ID_SIZE], const char *nodename)
{
......@@ -89,9 +91,40 @@ static void backend_changed(struct xenbus_watch *watch,
xenbus_otherend_changed(watch, vec, len, 1);
}
static void xenbus_frontend_delayed_resume(struct work_struct *w)
{
struct xenbus_device *xdev = container_of(w, struct xenbus_device, work);
xenbus_dev_resume(&xdev->dev);
}
static int xenbus_frontend_dev_resume(struct device *dev)
{
/*
* If xenstored is running in this domain, we cannot access the backend
* state at the moment, so we need to defer xenbus_dev_resume
*/
if (xen_store_domain_type == XS_LOCAL) {
struct xenbus_device *xdev = to_xenbus_device(dev);
if (!xenbus_frontend_wq) {
pr_err("%s: no workqueue to process delayed resume\n",
xdev->nodename);
return -EFAULT;
}
INIT_WORK(&xdev->work, xenbus_frontend_delayed_resume);
queue_work(xenbus_frontend_wq, &xdev->work);
return 0;
}
return xenbus_dev_resume(dev);
}
static const struct dev_pm_ops xenbus_pm_ops = {
.suspend = xenbus_dev_suspend,
.resume = xenbus_dev_resume,
.resume = xenbus_frontend_dev_resume,
.freeze = xenbus_dev_suspend,
.thaw = xenbus_dev_cancel,
.restore = xenbus_dev_resume,
......@@ -440,6 +473,8 @@ static int __init xenbus_probe_frontend_init(void)
register_xenstore_notifier(&xenstore_notifier);
xenbus_frontend_wq = create_workqueue("xenbus_frontend");
return 0;
}
subsys_initcall(xenbus_probe_frontend_init);
......
......@@ -70,6 +70,7 @@ struct xenbus_device {
struct device dev;
enum xenbus_state state;
struct completion down;
struct work_struct work;
};
static inline struct xenbus_device *to_xenbus_device(struct device *dev)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment