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, ...@@ -576,24 +576,22 @@ void xen_send_IPI_mask_allbutself(const struct cpumask *mask,
{ {
unsigned cpu; unsigned cpu;
unsigned int this_cpu = smp_processor_id(); 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; return;
for_each_cpu_and(cpu, mask, cpu_online_mask) { for_each_cpu_and(cpu, mask, cpu_online_mask) {
if (this_cpu == cpu) if (this_cpu == cpu)
continue; continue;
xen_smp_send_call_function_single_ipi(cpu); xen_send_IPI_one(cpu, xen_vector);
} }
} }
void xen_send_IPI_allbutself(int vector) void xen_send_IPI_allbutself(int vector)
{ {
int xen_vector = xen_map_vector(vector); xen_send_IPI_mask_allbutself(cpu_online_mask, vector);
if (xen_vector >= 0)
xen_send_IPI_mask_allbutself(cpu_online_mask, xen_vector);
} }
static irqreturn_t xen_call_function_interrupt(int irq, void *dev_id) 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, ...@@ -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, extern void xen_send_IPI_mask_allbutself(const struct cpumask *mask,
int vector); int vector);
extern void xen_send_IPI_allbutself(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_all(int vector);
extern void xen_send_IPI_self(int vector); extern void xen_send_IPI_self(int vector);
......
...@@ -41,6 +41,8 @@ module_param(selfballooning, bool, S_IRUGO); ...@@ -41,6 +41,8 @@ module_param(selfballooning, bool, S_IRUGO);
#ifdef CONFIG_FRONTSWAP #ifdef CONFIG_FRONTSWAP
static bool frontswap __read_mostly = true; static bool frontswap __read_mostly = true;
module_param(frontswap, bool, S_IRUGO); module_param(frontswap, bool, S_IRUGO);
#else /* CONFIG_FRONTSWAP */
#define frontswap (0)
#endif /* CONFIG_FRONTSWAP */ #endif /* CONFIG_FRONTSWAP */
#ifdef CONFIG_XEN_SELFBALLOONING #ifdef CONFIG_XEN_SELFBALLOONING
......
...@@ -106,7 +106,7 @@ static void pcistub_device_release(struct kref *kref) ...@@ -106,7 +106,7 @@ static void pcistub_device_release(struct kref *kref)
else else
pci_restore_state(dev); pci_restore_state(dev);
if (pci_find_capability(dev, PCI_CAP_ID_MSIX)) { if (dev->msix_cap) {
struct physdev_pci_device ppdev = { struct physdev_pci_device ppdev = {
.seg = pci_domain_nr(dev->bus), .seg = pci_domain_nr(dev->bus),
.bus = dev->bus->number, .bus = dev->bus->number,
...@@ -371,7 +371,7 @@ static int pcistub_init_device(struct pci_dev *dev) ...@@ -371,7 +371,7 @@ static int pcistub_init_device(struct pci_dev *dev)
if (err) if (err)
goto config_release; goto config_release;
if (pci_find_capability(dev, PCI_CAP_ID_MSIX)) { if (dev->msix_cap) {
struct physdev_pci_device ppdev = { struct physdev_pci_device ppdev = {
.seg = pci_domain_nr(dev->bus), .seg = pci_domain_nr(dev->bus),
.bus = dev->bus->number, .bus = dev->bus->number,
......
...@@ -534,7 +534,7 @@ static int xenbus_map_ring_valloc_hvm(struct xenbus_device *dev, ...@@ -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); err = xenbus_map_ring(dev, gnt_ref, &node->handle, addr);
if (err) if (err)
goto out_err; goto out_err_free_ballooned_pages;
spin_lock(&xenbus_valloc_lock); spin_lock(&xenbus_valloc_lock);
list_add(&node->next, &xenbus_valloc_pages); list_add(&node->next, &xenbus_valloc_pages);
...@@ -543,8 +543,9 @@ static int xenbus_map_ring_valloc_hvm(struct xenbus_device *dev, ...@@ -543,8 +543,9 @@ static int xenbus_map_ring_valloc_hvm(struct xenbus_device *dev,
*vaddr = addr; *vaddr = addr;
return 0; return 0;
out_err: out_err_free_ballooned_pages:
free_xenballooned_pages(1, &node->page); free_xenballooned_pages(1, &node->page);
out_err:
kfree(node); kfree(node);
return err; return err;
} }
......
...@@ -45,6 +45,7 @@ int xb_wait_for_data_to_read(void); ...@@ -45,6 +45,7 @@ int xb_wait_for_data_to_read(void);
int xs_input_avail(void); int xs_input_avail(void);
extern struct xenstore_domain_interface *xen_store_interface; extern struct xenstore_domain_interface *xen_store_interface;
extern int xen_store_evtchn; extern int xen_store_evtchn;
extern enum xenstore_init xen_store_domain_type;
extern const struct file_operations xen_xenbus_fops; extern const struct file_operations xen_xenbus_fops;
......
...@@ -69,6 +69,9 @@ EXPORT_SYMBOL_GPL(xen_store_evtchn); ...@@ -69,6 +69,9 @@ EXPORT_SYMBOL_GPL(xen_store_evtchn);
struct xenstore_domain_interface *xen_store_interface; struct xenstore_domain_interface *xen_store_interface;
EXPORT_SYMBOL_GPL(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 unsigned long xen_store_mfn;
static BLOCKING_NOTIFIER_HEAD(xenstore_chain); static BLOCKING_NOTIFIER_HEAD(xenstore_chain);
...@@ -719,17 +722,11 @@ static int __init xenstored_local_init(void) ...@@ -719,17 +722,11 @@ static int __init xenstored_local_init(void)
return err; return err;
} }
enum xenstore_init {
UNKNOWN,
PV,
HVM,
LOCAL,
};
static int __init xenbus_init(void) static int __init xenbus_init(void)
{ {
int err = 0; int err = 0;
enum xenstore_init usage = UNKNOWN;
uint64_t v = 0; uint64_t v = 0;
xen_store_domain_type = XS_UNKNOWN;
if (!xen_domain()) if (!xen_domain())
return -ENODEV; return -ENODEV;
...@@ -737,29 +734,29 @@ static int __init xenbus_init(void) ...@@ -737,29 +734,29 @@ static int __init xenbus_init(void)
xenbus_ring_ops_init(); xenbus_ring_ops_init();
if (xen_pv_domain()) if (xen_pv_domain())
usage = PV; xen_store_domain_type = XS_PV;
if (xen_hvm_domain()) if (xen_hvm_domain())
usage = HVM; xen_store_domain_type = XS_HVM;
if (xen_hvm_domain() && xen_initial_domain()) if (xen_hvm_domain() && xen_initial_domain())
usage = LOCAL; xen_store_domain_type = XS_LOCAL;
if (xen_pv_domain() && !xen_start_info->store_evtchn) 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) if (xen_pv_domain() && xen_start_info->store_evtchn)
xenstored_ready = 1; xenstored_ready = 1;
switch (usage) { switch (xen_store_domain_type) {
case LOCAL: case XS_LOCAL:
err = xenstored_local_init(); err = xenstored_local_init();
if (err) if (err)
goto out_error; goto out_error;
xen_store_interface = mfn_to_virt(xen_store_mfn); xen_store_interface = mfn_to_virt(xen_store_mfn);
break; break;
case PV: case XS_PV:
xen_store_evtchn = xen_start_info->store_evtchn; xen_store_evtchn = xen_start_info->store_evtchn;
xen_store_mfn = xen_start_info->store_mfn; xen_store_mfn = xen_start_info->store_mfn;
xen_store_interface = mfn_to_virt(xen_store_mfn); xen_store_interface = mfn_to_virt(xen_store_mfn);
break; break;
case HVM: case XS_HVM:
err = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v); err = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v);
if (err) if (err)
goto out_error; goto out_error;
......
...@@ -47,6 +47,13 @@ struct xen_bus_type { ...@@ -47,6 +47,13 @@ struct xen_bus_type {
struct bus_type bus; struct bus_type bus;
}; };
enum xenstore_init {
XS_UNKNOWN,
XS_PV,
XS_HVM,
XS_LOCAL,
};
extern struct device_attribute xenbus_dev_attrs[]; extern struct device_attribute xenbus_dev_attrs[];
extern int xenbus_match(struct device *_dev, struct device_driver *_drv); extern int xenbus_match(struct device *_dev, struct device_driver *_drv);
......
...@@ -29,6 +29,8 @@ ...@@ -29,6 +29,8 @@
#include "xenbus_probe.h" #include "xenbus_probe.h"
static struct workqueue_struct *xenbus_frontend_wq;
/* device/<type>/<id> => <type>-<id> */ /* device/<type>/<id> => <type>-<id> */
static int frontend_bus_id(char bus_id[XEN_BUS_ID_SIZE], const char *nodename) 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, ...@@ -89,9 +91,40 @@ static void backend_changed(struct xenbus_watch *watch,
xenbus_otherend_changed(watch, vec, len, 1); 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 = { static const struct dev_pm_ops xenbus_pm_ops = {
.suspend = xenbus_dev_suspend, .suspend = xenbus_dev_suspend,
.resume = xenbus_dev_resume, .resume = xenbus_frontend_dev_resume,
.freeze = xenbus_dev_suspend, .freeze = xenbus_dev_suspend,
.thaw = xenbus_dev_cancel, .thaw = xenbus_dev_cancel,
.restore = xenbus_dev_resume, .restore = xenbus_dev_resume,
...@@ -440,6 +473,8 @@ static int __init xenbus_probe_frontend_init(void) ...@@ -440,6 +473,8 @@ static int __init xenbus_probe_frontend_init(void)
register_xenstore_notifier(&xenstore_notifier); register_xenstore_notifier(&xenstore_notifier);
xenbus_frontend_wq = create_workqueue("xenbus_frontend");
return 0; return 0;
} }
subsys_initcall(xenbus_probe_frontend_init); subsys_initcall(xenbus_probe_frontend_init);
......
...@@ -70,6 +70,7 @@ struct xenbus_device { ...@@ -70,6 +70,7 @@ struct xenbus_device {
struct device dev; struct device dev;
enum xenbus_state state; enum xenbus_state state;
struct completion down; struct completion down;
struct work_struct work;
}; };
static inline struct xenbus_device *to_xenbus_device(struct device *dev) 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