diff options
Diffstat (limited to 'drivers/xen')
-rw-r--r-- | drivers/xen/events/events_fifo.c | 41 | ||||
-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 |
5 files changed, 105 insertions, 17 deletions
diff --git a/drivers/xen/events/events_fifo.c b/drivers/xen/events/events_fifo.c index 96109a9972b6..84b4bfb84344 100644 --- a/drivers/xen/events/events_fifo.c +++ b/drivers/xen/events/events_fifo.c | |||
@@ -66,7 +66,22 @@ static DEFINE_PER_CPU(struct evtchn_fifo_queue, cpu_queue); | |||
66 | static event_word_t *event_array[MAX_EVENT_ARRAY_PAGES] __read_mostly; | 66 | static event_word_t *event_array[MAX_EVENT_ARRAY_PAGES] __read_mostly; |
67 | static unsigned event_array_pages __read_mostly; | 67 | static unsigned event_array_pages __read_mostly; |
68 | 68 | ||
69 | /* | ||
70 | * sync_set_bit() and friends must be unsigned long aligned on non-x86 | ||
71 | * platforms. | ||
72 | */ | ||
73 | #if !defined(CONFIG_X86) && BITS_PER_LONG > 32 | ||
74 | |||
75 | #define BM(w) (unsigned long *)((unsigned long)w & ~0x7UL) | ||
76 | #define EVTCHN_FIFO_BIT(b, w) \ | ||
77 | (((unsigned long)w & 0x4UL) ? (EVTCHN_FIFO_ ##b + 32) : EVTCHN_FIFO_ ##b) | ||
78 | |||
79 | #else | ||
80 | |||
69 | #define BM(w) ((unsigned long *)(w)) | 81 | #define BM(w) ((unsigned long *)(w)) |
82 | #define EVTCHN_FIFO_BIT(b, w) EVTCHN_FIFO_ ##b | ||
83 | |||
84 | #endif | ||
70 | 85 | ||
71 | static inline event_word_t *event_word_from_port(unsigned port) | 86 | static inline event_word_t *event_word_from_port(unsigned port) |
72 | { | 87 | { |
@@ -161,33 +176,38 @@ static void evtchn_fifo_bind_to_cpu(struct irq_info *info, unsigned cpu) | |||
161 | static void evtchn_fifo_clear_pending(unsigned port) | 176 | static void evtchn_fifo_clear_pending(unsigned port) |
162 | { | 177 | { |
163 | event_word_t *word = event_word_from_port(port); | 178 | event_word_t *word = event_word_from_port(port); |
164 | sync_clear_bit(EVTCHN_FIFO_PENDING, BM(word)); | 179 | sync_clear_bit(EVTCHN_FIFO_BIT(PENDING, word), BM(word)); |
165 | } | 180 | } |
166 | 181 | ||
167 | static void evtchn_fifo_set_pending(unsigned port) | 182 | static void evtchn_fifo_set_pending(unsigned port) |
168 | { | 183 | { |
169 | event_word_t *word = event_word_from_port(port); | 184 | event_word_t *word = event_word_from_port(port); |
170 | sync_set_bit(EVTCHN_FIFO_PENDING, BM(word)); | 185 | sync_set_bit(EVTCHN_FIFO_BIT(PENDING, word), BM(word)); |
171 | } | 186 | } |
172 | 187 | ||
173 | static bool evtchn_fifo_is_pending(unsigned port) | 188 | static bool evtchn_fifo_is_pending(unsigned port) |
174 | { | 189 | { |
175 | event_word_t *word = event_word_from_port(port); | 190 | event_word_t *word = event_word_from_port(port); |
176 | return sync_test_bit(EVTCHN_FIFO_PENDING, BM(word)); | 191 | return sync_test_bit(EVTCHN_FIFO_BIT(PENDING, word), BM(word)); |
177 | } | 192 | } |
178 | 193 | ||
179 | static bool evtchn_fifo_test_and_set_mask(unsigned port) | 194 | static bool evtchn_fifo_test_and_set_mask(unsigned port) |
180 | { | 195 | { |
181 | event_word_t *word = event_word_from_port(port); | 196 | event_word_t *word = event_word_from_port(port); |
182 | return sync_test_and_set_bit(EVTCHN_FIFO_MASKED, BM(word)); | 197 | return sync_test_and_set_bit(EVTCHN_FIFO_BIT(MASKED, word), BM(word)); |
183 | } | 198 | } |
184 | 199 | ||
185 | static void evtchn_fifo_mask(unsigned port) | 200 | static void evtchn_fifo_mask(unsigned port) |
186 | { | 201 | { |
187 | event_word_t *word = event_word_from_port(port); | 202 | event_word_t *word = event_word_from_port(port); |
188 | sync_set_bit(EVTCHN_FIFO_MASKED, BM(word)); | 203 | sync_set_bit(EVTCHN_FIFO_BIT(MASKED, word), BM(word)); |
189 | } | 204 | } |
190 | 205 | ||
206 | static bool evtchn_fifo_is_masked(unsigned port) | ||
207 | { | ||
208 | event_word_t *word = event_word_from_port(port); | ||
209 | return sync_test_bit(EVTCHN_FIFO_BIT(MASKED, word), BM(word)); | ||
210 | } | ||
191 | /* | 211 | /* |
192 | * Clear MASKED, spinning if BUSY is set. | 212 | * Clear MASKED, spinning if BUSY is set. |
193 | */ | 213 | */ |
@@ -211,7 +231,7 @@ static void evtchn_fifo_unmask(unsigned port) | |||
211 | BUG_ON(!irqs_disabled()); | 231 | BUG_ON(!irqs_disabled()); |
212 | 232 | ||
213 | clear_masked(word); | 233 | clear_masked(word); |
214 | if (sync_test_bit(EVTCHN_FIFO_PENDING, BM(word))) { | 234 | if (evtchn_fifo_is_pending(port)) { |
215 | struct evtchn_unmask unmask = { .port = port }; | 235 | struct evtchn_unmask unmask = { .port = port }; |
216 | (void)HYPERVISOR_event_channel_op(EVTCHNOP_unmask, &unmask); | 236 | (void)HYPERVISOR_event_channel_op(EVTCHNOP_unmask, &unmask); |
217 | } | 237 | } |
@@ -243,7 +263,7 @@ static void handle_irq_for_port(unsigned port) | |||
243 | 263 | ||
244 | static void consume_one_event(unsigned cpu, | 264 | static void consume_one_event(unsigned cpu, |
245 | struct evtchn_fifo_control_block *control_block, | 265 | struct evtchn_fifo_control_block *control_block, |
246 | unsigned priority, uint32_t *ready) | 266 | unsigned priority, unsigned long *ready) |
247 | { | 267 | { |
248 | struct evtchn_fifo_queue *q = &per_cpu(cpu_queue, cpu); | 268 | struct evtchn_fifo_queue *q = &per_cpu(cpu_queue, cpu); |
249 | uint32_t head; | 269 | uint32_t head; |
@@ -273,10 +293,9 @@ static void consume_one_event(unsigned cpu, | |||
273 | * copy of the ready word. | 293 | * copy of the ready word. |
274 | */ | 294 | */ |
275 | if (head == 0) | 295 | if (head == 0) |
276 | clear_bit(priority, BM(ready)); | 296 | clear_bit(priority, ready); |
277 | 297 | ||
278 | if (sync_test_bit(EVTCHN_FIFO_PENDING, BM(word)) | 298 | if (evtchn_fifo_is_pending(port) && !evtchn_fifo_is_masked(port)) |
279 | && !sync_test_bit(EVTCHN_FIFO_MASKED, BM(word))) | ||
280 | handle_irq_for_port(port); | 299 | handle_irq_for_port(port); |
281 | 300 | ||
282 | q->head[priority] = head; | 301 | q->head[priority] = head; |
@@ -285,7 +304,7 @@ static void consume_one_event(unsigned cpu, | |||
285 | static void evtchn_fifo_handle_events(unsigned cpu) | 304 | static void evtchn_fifo_handle_events(unsigned cpu) |
286 | { | 305 | { |
287 | struct evtchn_fifo_control_block *control_block; | 306 | struct evtchn_fifo_control_block *control_block; |
288 | uint32_t ready; | 307 | unsigned long ready; |
289 | unsigned q; | 308 | unsigned q; |
290 | 309 | ||
291 | control_block = per_cpu(cpu_control_block, cpu); | 310 | control_block = per_cpu(cpu_control_block, cpu); |
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))) |