diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-17 13:54:07 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-17 13:54:07 -0400 |
commit | 88764e0a3ecf655950c4d46b323cf80e2e0ee481 (patch) | |
tree | 395682bc8b0071ccf0124c5a7b952c0ca855fef7 /drivers | |
parent | 23c1a60e2e9d7d07f5f686e6413fc92bfb84366f (diff) | |
parent | eb47f71200b7d5b4c8c1f8c75675f592d855aafd (diff) |
Merge tag 'stable/for-linus-3.15-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip
Pull Xen fixes from David Vrabel:
"Xen regression and bug fixes for 3.15-rc1:
- fix completely broken 32-bit PV guests caused by x86 refactoring
32-bit thread_info.
- only enable ticketlock slow path on Xen (not bare metal)
- fix two bugs with PV guests not shutting down when requested
- fix a minor memory leak in xen-pciback error path"
* tag 'stable/for-linus-3.15-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip:
xen/manage: Poweroff forcefully if user-space is not yet up.
xen/xenbus: Avoid synchronous wait on XenBus stalling shutdown/restart.
xen/spinlock: Don't enable them unconditionally.
xen-pciback: silence an unwanted debug printk
xen: fix memory leak in __xen_pcibk_add_pci_dev()
x86/xen: Fix 32-bit PV guests's usage of kernel_stack
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/xen/manage.c | 32 | ||||
-rw-r--r-- | drivers/xen/xen-pciback/pciback_ops.c | 3 | ||||
-rw-r--r-- | drivers/xen/xen-pciback/vpci.c | 2 | ||||
-rw-r--r-- | drivers/xen/xenbus/xenbus_xs.c | 44 |
4 files changed, 75 insertions, 6 deletions
diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c index fc6c94c0b436..32f9236c959f 100644 --- a/drivers/xen/manage.c +++ b/drivers/xen/manage.c | |||
@@ -198,10 +198,32 @@ struct shutdown_handler { | |||
198 | void (*cb)(void); | 198 | void (*cb)(void); |
199 | }; | 199 | }; |
200 | 200 | ||
201 | static int poweroff_nb(struct notifier_block *cb, unsigned long code, void *unused) | ||
202 | { | ||
203 | switch (code) { | ||
204 | case SYS_DOWN: | ||
205 | case SYS_HALT: | ||
206 | case SYS_POWER_OFF: | ||
207 | shutting_down = SHUTDOWN_POWEROFF; | ||
208 | default: | ||
209 | break; | ||
210 | } | ||
211 | return NOTIFY_DONE; | ||
212 | } | ||
201 | static void do_poweroff(void) | 213 | static void do_poweroff(void) |
202 | { | 214 | { |
203 | shutting_down = SHUTDOWN_POWEROFF; | 215 | switch (system_state) { |
204 | orderly_poweroff(false); | 216 | case SYSTEM_BOOTING: |
217 | orderly_poweroff(true); | ||
218 | break; | ||
219 | case SYSTEM_RUNNING: | ||
220 | orderly_poweroff(false); | ||
221 | break; | ||
222 | default: | ||
223 | /* Don't do it when we are halting/rebooting. */ | ||
224 | pr_info("Ignoring Xen toolstack shutdown.\n"); | ||
225 | break; | ||
226 | } | ||
205 | } | 227 | } |
206 | 228 | ||
207 | static void do_reboot(void) | 229 | static void do_reboot(void) |
@@ -307,6 +329,10 @@ static struct xenbus_watch shutdown_watch = { | |||
307 | .callback = shutdown_handler | 329 | .callback = shutdown_handler |
308 | }; | 330 | }; |
309 | 331 | ||
332 | static struct notifier_block xen_reboot_nb = { | ||
333 | .notifier_call = poweroff_nb, | ||
334 | }; | ||
335 | |||
310 | static int setup_shutdown_watcher(void) | 336 | static int setup_shutdown_watcher(void) |
311 | { | 337 | { |
312 | int err; | 338 | int err; |
@@ -317,6 +343,7 @@ static int setup_shutdown_watcher(void) | |||
317 | return err; | 343 | return err; |
318 | } | 344 | } |
319 | 345 | ||
346 | |||
320 | #ifdef CONFIG_MAGIC_SYSRQ | 347 | #ifdef CONFIG_MAGIC_SYSRQ |
321 | err = register_xenbus_watch(&sysrq_watch); | 348 | err = register_xenbus_watch(&sysrq_watch); |
322 | if (err) { | 349 | if (err) { |
@@ -345,6 +372,7 @@ int xen_setup_shutdown_event(void) | |||
345 | if (!xen_domain()) | 372 | if (!xen_domain()) |
346 | return -ENODEV; | 373 | return -ENODEV; |
347 | register_xenstore_notifier(&xenstore_notifier); | 374 | register_xenstore_notifier(&xenstore_notifier); |
375 | register_reboot_notifier(&xen_reboot_nb); | ||
348 | 376 | ||
349 | return 0; | 377 | return 0; |
350 | } | 378 | } |
diff --git a/drivers/xen/xen-pciback/pciback_ops.c b/drivers/xen/xen-pciback/pciback_ops.c index 929dd46bb40c..607e41460c0d 100644 --- a/drivers/xen/xen-pciback/pciback_ops.c +++ b/drivers/xen/xen-pciback/pciback_ops.c | |||
@@ -217,7 +217,7 @@ int xen_pcibk_enable_msix(struct xen_pcibk_device *pdev, | |||
217 | if (result == 0) { | 217 | if (result == 0) { |
218 | for (i = 0; i < op->value; i++) { | 218 | for (i = 0; i < op->value; i++) { |
219 | op->msix_entries[i].entry = entries[i].entry; | 219 | op->msix_entries[i].entry = entries[i].entry; |
220 | if (entries[i].vector) | 220 | if (entries[i].vector) { |
221 | op->msix_entries[i].vector = | 221 | op->msix_entries[i].vector = |
222 | xen_pirq_from_irq(entries[i].vector); | 222 | xen_pirq_from_irq(entries[i].vector); |
223 | if (unlikely(verbose_request)) | 223 | if (unlikely(verbose_request)) |
@@ -225,6 +225,7 @@ int xen_pcibk_enable_msix(struct xen_pcibk_device *pdev, | |||
225 | "MSI-X[%d]: %d\n", | 225 | "MSI-X[%d]: %d\n", |
226 | pci_name(dev), i, | 226 | pci_name(dev), i, |
227 | op->msix_entries[i].vector); | 227 | op->msix_entries[i].vector); |
228 | } | ||
228 | } | 229 | } |
229 | } else | 230 | } else |
230 | pr_warn_ratelimited("%s: error enabling MSI-X for guest %u: err %d!\n", | 231 | pr_warn_ratelimited("%s: error enabling MSI-X for guest %u: err %d!\n", |
diff --git a/drivers/xen/xen-pciback/vpci.c b/drivers/xen/xen-pciback/vpci.c index 3165ce361b00..51afff96c515 100644 --- a/drivers/xen/xen-pciback/vpci.c +++ b/drivers/xen/xen-pciback/vpci.c | |||
@@ -137,6 +137,8 @@ unlock: | |||
137 | /* Publish this device. */ | 137 | /* Publish this device. */ |
138 | if (!err) | 138 | if (!err) |
139 | err = publish_cb(pdev, 0, 0, PCI_DEVFN(slot, func), devid); | 139 | err = publish_cb(pdev, 0, 0, PCI_DEVFN(slot, func), devid); |
140 | else | ||
141 | kfree(dev_entry); | ||
140 | 142 | ||
141 | out: | 143 | out: |
142 | return err; | 144 | return err; |
diff --git a/drivers/xen/xenbus/xenbus_xs.c b/drivers/xen/xenbus/xenbus_xs.c index b6d5fff43d16..ba804f3d8278 100644 --- a/drivers/xen/xenbus/xenbus_xs.c +++ b/drivers/xen/xenbus/xenbus_xs.c | |||
@@ -50,6 +50,7 @@ | |||
50 | #include <xen/xenbus.h> | 50 | #include <xen/xenbus.h> |
51 | #include <xen/xen.h> | 51 | #include <xen/xen.h> |
52 | #include "xenbus_comms.h" | 52 | #include "xenbus_comms.h" |
53 | #include "xenbus_probe.h" | ||
53 | 54 | ||
54 | struct xs_stored_msg { | 55 | struct xs_stored_msg { |
55 | struct list_head list; | 56 | struct list_head list; |
@@ -139,6 +140,29 @@ static int get_error(const char *errorstring) | |||
139 | return xsd_errors[i].errnum; | 140 | return xsd_errors[i].errnum; |
140 | } | 141 | } |
141 | 142 | ||
143 | static bool xenbus_ok(void) | ||
144 | { | ||
145 | switch (xen_store_domain_type) { | ||
146 | case XS_LOCAL: | ||
147 | switch (system_state) { | ||
148 | case SYSTEM_POWER_OFF: | ||
149 | case SYSTEM_RESTART: | ||
150 | case SYSTEM_HALT: | ||
151 | return false; | ||
152 | default: | ||
153 | break; | ||
154 | } | ||
155 | return true; | ||
156 | case XS_PV: | ||
157 | case XS_HVM: | ||
158 | /* FIXME: Could check that the remote domain is alive, | ||
159 | * but it is normally initial domain. */ | ||
160 | return true; | ||
161 | default: | ||
162 | break; | ||
163 | } | ||
164 | return false; | ||
165 | } | ||
142 | static void *read_reply(enum xsd_sockmsg_type *type, unsigned int *len) | 166 | static void *read_reply(enum xsd_sockmsg_type *type, unsigned int *len) |
143 | { | 167 | { |
144 | struct xs_stored_msg *msg; | 168 | struct xs_stored_msg *msg; |
@@ -148,9 +172,20 @@ static void *read_reply(enum xsd_sockmsg_type *type, unsigned int *len) | |||
148 | 172 | ||
149 | while (list_empty(&xs_state.reply_list)) { | 173 | while (list_empty(&xs_state.reply_list)) { |
150 | spin_unlock(&xs_state.reply_lock); | 174 | spin_unlock(&xs_state.reply_lock); |
151 | /* XXX FIXME: Avoid synchronous wait for response here. */ | 175 | if (xenbus_ok()) |
152 | wait_event(xs_state.reply_waitq, | 176 | /* XXX FIXME: Avoid synchronous wait for response here. */ |
153 | !list_empty(&xs_state.reply_list)); | 177 | wait_event_timeout(xs_state.reply_waitq, |
178 | !list_empty(&xs_state.reply_list), | ||
179 | msecs_to_jiffies(500)); | ||
180 | else { | ||
181 | /* | ||
182 | * If we are in the process of being shut-down there is | ||
183 | * no point of trying to contact XenBus - it is either | ||
184 | * killed (xenstored application) or the other domain | ||
185 | * has been killed or is unreachable. | ||
186 | */ | ||
187 | return ERR_PTR(-EIO); | ||
188 | } | ||
154 | spin_lock(&xs_state.reply_lock); | 189 | spin_lock(&xs_state.reply_lock); |
155 | } | 190 | } |
156 | 191 | ||
@@ -215,6 +250,9 @@ void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg) | |||
215 | 250 | ||
216 | mutex_unlock(&xs_state.request_mutex); | 251 | mutex_unlock(&xs_state.request_mutex); |
217 | 252 | ||
253 | if (IS_ERR(ret)) | ||
254 | return ret; | ||
255 | |||
218 | if ((msg->type == XS_TRANSACTION_END) || | 256 | if ((msg->type == XS_TRANSACTION_END) || |
219 | ((req_msg.type == XS_TRANSACTION_START) && | 257 | ((req_msg.type == XS_TRANSACTION_START) && |
220 | (msg->type == XS_ERROR))) | 258 | (msg->type == XS_ERROR))) |