diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2014-07-24 15:36:56 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2014-07-24 15:36:56 -0400 |
commit | b9f12a5d97f652c77ef6803dccd0d40d1290f5be (patch) | |
tree | 8f58c8620ffef0d350a5ec022feda492a96b179a /drivers/xen | |
parent | 9d8dc3e529a19e427fd379118acd132520935c5d (diff) | |
parent | 9a3c4145af32125c5ee39c0272662b47307a8323 (diff) |
Merge tag 'v3.16-rc6' into next
Merge with mainline to bring in changes to MFD to allow merging
ipaq-micro-ts driver.
Diffstat (limited to 'drivers/xen')
-rw-r--r-- | drivers/xen/balloon.c | 12 | ||||
-rw-r--r-- | drivers/xen/events/events_base.c | 17 | ||||
-rw-r--r-- | drivers/xen/events/events_fifo.c | 41 | ||||
-rw-r--r-- | drivers/xen/grant-table.c | 3 | ||||
-rw-r--r-- | drivers/xen/manage.c | 50 | ||||
-rw-r--r-- | drivers/xen/xen-acpi-processor.c | 4 | ||||
-rw-r--r-- | drivers/xen/xen-pciback/pci_stub.c | 25 | ||||
-rw-r--r-- | drivers/xen/xen-pciback/pciback_ops.c | 4 | ||||
-rw-r--r-- | drivers/xen/xen-pciback/xenbus.c | 4 |
9 files changed, 77 insertions, 83 deletions
diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index b7a506f2bb14..5c660c77f03b 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c | |||
@@ -426,20 +426,18 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp) | |||
426 | * p2m are consistent. | 426 | * p2m are consistent. |
427 | */ | 427 | */ |
428 | if (!xen_feature(XENFEAT_auto_translated_physmap)) { | 428 | if (!xen_feature(XENFEAT_auto_translated_physmap)) { |
429 | unsigned long p; | ||
430 | struct page *scratch_page = get_balloon_scratch_page(); | ||
431 | |||
432 | if (!PageHighMem(page)) { | 429 | if (!PageHighMem(page)) { |
430 | struct page *scratch_page = get_balloon_scratch_page(); | ||
431 | |||
433 | ret = HYPERVISOR_update_va_mapping( | 432 | ret = HYPERVISOR_update_va_mapping( |
434 | (unsigned long)__va(pfn << PAGE_SHIFT), | 433 | (unsigned long)__va(pfn << PAGE_SHIFT), |
435 | pfn_pte(page_to_pfn(scratch_page), | 434 | pfn_pte(page_to_pfn(scratch_page), |
436 | PAGE_KERNEL_RO), 0); | 435 | PAGE_KERNEL_RO), 0); |
437 | BUG_ON(ret); | 436 | BUG_ON(ret); |
438 | } | ||
439 | p = page_to_pfn(scratch_page); | ||
440 | __set_phys_to_machine(pfn, pfn_to_mfn(p)); | ||
441 | 437 | ||
442 | put_balloon_scratch_page(); | 438 | put_balloon_scratch_page(); |
439 | } | ||
440 | __set_phys_to_machine(pfn, INVALID_P2M_ENTRY); | ||
443 | } | 441 | } |
444 | #endif | 442 | #endif |
445 | 443 | ||
diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c index dfa12a4a0a48..c919d3d5c845 100644 --- a/drivers/xen/events/events_base.c +++ b/drivers/xen/events/events_base.c | |||
@@ -390,22 +390,7 @@ static void xen_irq_init(unsigned irq) | |||
390 | 390 | ||
391 | static int __must_check xen_allocate_irqs_dynamic(int nvec) | 391 | static int __must_check xen_allocate_irqs_dynamic(int nvec) |
392 | { | 392 | { |
393 | int first = 0; | 393 | int i, irq = irq_alloc_descs(-1, 0, nvec, -1); |
394 | int i, irq; | ||
395 | |||
396 | #ifdef CONFIG_X86_IO_APIC | ||
397 | /* | ||
398 | * For an HVM guest or domain 0 which see "real" (emulated or | ||
399 | * actual respectively) GSIs we allocate dynamic IRQs | ||
400 | * e.g. those corresponding to event channels or MSIs | ||
401 | * etc. from the range above those "real" GSIs to avoid | ||
402 | * collisions. | ||
403 | */ | ||
404 | if (xen_initial_domain() || xen_hvm_domain()) | ||
405 | first = get_nr_irqs_gsi(); | ||
406 | #endif | ||
407 | |||
408 | irq = irq_alloc_descs_from(first, nvec, -1); | ||
409 | 394 | ||
410 | if (irq >= 0) { | 395 | if (irq >= 0) { |
411 | for (i = 0; i < nvec; i++) | 396 | for (i = 0; i < nvec; i++) |
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/grant-table.c b/drivers/xen/grant-table.c index 6d325bda76da..5d4de88fe5b8 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c | |||
@@ -1168,7 +1168,8 @@ int gnttab_resume(void) | |||
1168 | 1168 | ||
1169 | int gnttab_suspend(void) | 1169 | int gnttab_suspend(void) |
1170 | { | 1170 | { |
1171 | gnttab_interface->unmap_frames(); | 1171 | if (!xen_feature(XENFEAT_auto_translated_physmap)) |
1172 | gnttab_interface->unmap_frames(); | ||
1172 | return 0; | 1173 | return 0; |
1173 | } | 1174 | } |
1174 | 1175 | ||
diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c index 32f9236c959f..5f1e1f3cd186 100644 --- a/drivers/xen/manage.c +++ b/drivers/xen/manage.c | |||
@@ -41,9 +41,6 @@ static enum shutdown_state shutting_down = SHUTDOWN_INVALID; | |||
41 | 41 | ||
42 | struct suspend_info { | 42 | struct suspend_info { |
43 | int cancelled; | 43 | int cancelled; |
44 | unsigned long arg; /* extra hypercall argument */ | ||
45 | void (*pre)(void); | ||
46 | void (*post)(int cancelled); | ||
47 | }; | 44 | }; |
48 | 45 | ||
49 | static RAW_NOTIFIER_HEAD(xen_resume_notifier); | 46 | static RAW_NOTIFIER_HEAD(xen_resume_notifier); |
@@ -61,26 +58,6 @@ void xen_resume_notifier_unregister(struct notifier_block *nb) | |||
61 | EXPORT_SYMBOL_GPL(xen_resume_notifier_unregister); | 58 | EXPORT_SYMBOL_GPL(xen_resume_notifier_unregister); |
62 | 59 | ||
63 | #ifdef CONFIG_HIBERNATE_CALLBACKS | 60 | #ifdef CONFIG_HIBERNATE_CALLBACKS |
64 | static void xen_hvm_post_suspend(int cancelled) | ||
65 | { | ||
66 | xen_arch_hvm_post_suspend(cancelled); | ||
67 | gnttab_resume(); | ||
68 | } | ||
69 | |||
70 | static void xen_pre_suspend(void) | ||
71 | { | ||
72 | xen_mm_pin_all(); | ||
73 | gnttab_suspend(); | ||
74 | xen_arch_pre_suspend(); | ||
75 | } | ||
76 | |||
77 | static void xen_post_suspend(int cancelled) | ||
78 | { | ||
79 | xen_arch_post_suspend(cancelled); | ||
80 | gnttab_resume(); | ||
81 | xen_mm_unpin_all(); | ||
82 | } | ||
83 | |||
84 | static int xen_suspend(void *data) | 61 | static int xen_suspend(void *data) |
85 | { | 62 | { |
86 | struct suspend_info *si = data; | 63 | struct suspend_info *si = data; |
@@ -94,22 +71,23 @@ static int xen_suspend(void *data) | |||
94 | return err; | 71 | return err; |
95 | } | 72 | } |
96 | 73 | ||
97 | if (si->pre) | 74 | gnttab_suspend(); |
98 | si->pre(); | 75 | xen_arch_pre_suspend(); |
99 | 76 | ||
100 | /* | 77 | /* |
101 | * This hypercall returns 1 if suspend was cancelled | 78 | * This hypercall returns 1 if suspend was cancelled |
102 | * or the domain was merely checkpointed, and 0 if it | 79 | * or the domain was merely checkpointed, and 0 if it |
103 | * is resuming in a new domain. | 80 | * is resuming in a new domain. |
104 | */ | 81 | */ |
105 | si->cancelled = HYPERVISOR_suspend(si->arg); | 82 | si->cancelled = HYPERVISOR_suspend(xen_pv_domain() |
83 | ? virt_to_mfn(xen_start_info) | ||
84 | : 0); | ||
106 | 85 | ||
107 | if (si->post) | 86 | xen_arch_post_suspend(si->cancelled); |
108 | si->post(si->cancelled); | 87 | gnttab_resume(); |
109 | 88 | ||
110 | if (!si->cancelled) { | 89 | if (!si->cancelled) { |
111 | xen_irq_resume(); | 90 | xen_irq_resume(); |
112 | xen_console_resume(); | ||
113 | xen_timer_resume(); | 91 | xen_timer_resume(); |
114 | } | 92 | } |
115 | 93 | ||
@@ -154,18 +132,12 @@ static void do_suspend(void) | |||
154 | 132 | ||
155 | si.cancelled = 1; | 133 | si.cancelled = 1; |
156 | 134 | ||
157 | if (xen_hvm_domain()) { | ||
158 | si.arg = 0UL; | ||
159 | si.pre = NULL; | ||
160 | si.post = &xen_hvm_post_suspend; | ||
161 | } else { | ||
162 | si.arg = virt_to_mfn(xen_start_info); | ||
163 | si.pre = &xen_pre_suspend; | ||
164 | si.post = &xen_post_suspend; | ||
165 | } | ||
166 | |||
167 | err = stop_machine(xen_suspend, &si, cpumask_of(0)); | 135 | err = stop_machine(xen_suspend, &si, cpumask_of(0)); |
168 | 136 | ||
137 | /* Resume console as early as possible. */ | ||
138 | if (!si.cancelled) | ||
139 | xen_console_resume(); | ||
140 | |||
169 | raw_notifier_call_chain(&xen_resume_notifier, 0, NULL); | 141 | raw_notifier_call_chain(&xen_resume_notifier, 0, NULL); |
170 | 142 | ||
171 | dpm_resume_start(si.cancelled ? PMSG_THAW : PMSG_RESTORE); | 143 | dpm_resume_start(si.cancelled ? PMSG_THAW : PMSG_RESTORE); |
diff --git a/drivers/xen/xen-acpi-processor.c b/drivers/xen/xen-acpi-processor.c index 82358d14ecf1..59fc190f1e92 100644 --- a/drivers/xen/xen-acpi-processor.c +++ b/drivers/xen/xen-acpi-processor.c | |||
@@ -127,7 +127,7 @@ static int push_cxx_to_hypervisor(struct acpi_processor *_pr) | |||
127 | pr_debug(" C%d: %s %d uS\n", | 127 | pr_debug(" C%d: %s %d uS\n", |
128 | cx->type, cx->desc, (u32)cx->latency); | 128 | cx->type, cx->desc, (u32)cx->latency); |
129 | } | 129 | } |
130 | } else if (ret != -EINVAL) | 130 | } else if ((ret != -EINVAL) && (ret != -ENOSYS)) |
131 | /* EINVAL means the ACPI ID is incorrect - meaning the ACPI | 131 | /* EINVAL means the ACPI ID is incorrect - meaning the ACPI |
132 | * table is referencing a non-existing CPU - which can happen | 132 | * table is referencing a non-existing CPU - which can happen |
133 | * with broken ACPI tables. */ | 133 | * with broken ACPI tables. */ |
@@ -259,7 +259,7 @@ static int push_pxx_to_hypervisor(struct acpi_processor *_pr) | |||
259 | (u32) perf->states[i].power, | 259 | (u32) perf->states[i].power, |
260 | (u32) perf->states[i].transition_latency); | 260 | (u32) perf->states[i].transition_latency); |
261 | } | 261 | } |
262 | } else if (ret != -EINVAL) | 262 | } else if ((ret != -EINVAL) && (ret != -ENOSYS)) |
263 | /* EINVAL means the ACPI ID is incorrect - meaning the ACPI | 263 | /* EINVAL means the ACPI ID is incorrect - meaning the ACPI |
264 | * table is referencing a non-existing CPU - which can happen | 264 | * table is referencing a non-existing CPU - which can happen |
265 | * with broken ACPI tables. */ | 265 | * with broken ACPI tables. */ |
diff --git a/drivers/xen/xen-pciback/pci_stub.c b/drivers/xen/xen-pciback/pci_stub.c index 62fcd485f0a7..d57a173685f3 100644 --- a/drivers/xen/xen-pciback/pci_stub.c +++ b/drivers/xen/xen-pciback/pci_stub.c | |||
@@ -242,6 +242,15 @@ struct pci_dev *pcistub_get_pci_dev(struct xen_pcibk_device *pdev, | |||
242 | return found_dev; | 242 | return found_dev; |
243 | } | 243 | } |
244 | 244 | ||
245 | /* | ||
246 | * Called when: | ||
247 | * - XenBus state has been reconfigure (pci unplug). See xen_pcibk_remove_device | ||
248 | * - XenBus state has been disconnected (guest shutdown). See xen_pcibk_xenbus_remove | ||
249 | * - 'echo BDF > unbind' on pciback module with no guest attached. See pcistub_remove | ||
250 | * - 'echo BDF > unbind' with a guest still using it. See pcistub_remove | ||
251 | * | ||
252 | * As such we have to be careful. | ||
253 | */ | ||
245 | void pcistub_put_pci_dev(struct pci_dev *dev) | 254 | void pcistub_put_pci_dev(struct pci_dev *dev) |
246 | { | 255 | { |
247 | struct pcistub_device *psdev, *found_psdev = NULL; | 256 | struct pcistub_device *psdev, *found_psdev = NULL; |
@@ -272,16 +281,16 @@ void pcistub_put_pci_dev(struct pci_dev *dev) | |||
272 | * and want to inhibit the user from fiddling with 'reset' | 281 | * and want to inhibit the user from fiddling with 'reset' |
273 | */ | 282 | */ |
274 | pci_reset_function(dev); | 283 | pci_reset_function(dev); |
275 | pci_restore_state(psdev->dev); | 284 | pci_restore_state(dev); |
276 | 285 | ||
277 | /* This disables the device. */ | 286 | /* This disables the device. */ |
278 | xen_pcibk_reset_device(found_psdev->dev); | 287 | xen_pcibk_reset_device(dev); |
279 | 288 | ||
280 | /* And cleanup up our emulated fields. */ | 289 | /* And cleanup up our emulated fields. */ |
281 | xen_pcibk_config_free_dyn_fields(found_psdev->dev); | 290 | xen_pcibk_config_reset_dev(dev); |
282 | xen_pcibk_config_reset_dev(found_psdev->dev); | 291 | xen_pcibk_config_free_dyn_fields(dev); |
283 | 292 | ||
284 | xen_unregister_device_domain_owner(found_psdev->dev); | 293 | xen_unregister_device_domain_owner(dev); |
285 | 294 | ||
286 | spin_lock_irqsave(&found_psdev->lock, flags); | 295 | spin_lock_irqsave(&found_psdev->lock, flags); |
287 | found_psdev->pdev = NULL; | 296 | found_psdev->pdev = NULL; |
@@ -493,6 +502,8 @@ static int pcistub_seize(struct pci_dev *dev) | |||
493 | return err; | 502 | return err; |
494 | } | 503 | } |
495 | 504 | ||
505 | /* Called when 'bind'. This means we must _NOT_ call pci_reset_function or | ||
506 | * other functions that take the sysfs lock. */ | ||
496 | static int pcistub_probe(struct pci_dev *dev, const struct pci_device_id *id) | 507 | static int pcistub_probe(struct pci_dev *dev, const struct pci_device_id *id) |
497 | { | 508 | { |
498 | int err = 0; | 509 | int err = 0; |
@@ -520,6 +531,8 @@ out: | |||
520 | return err; | 531 | return err; |
521 | } | 532 | } |
522 | 533 | ||
534 | /* Called when 'unbind'. This means we must _NOT_ call pci_reset_function or | ||
535 | * other functions that take the sysfs lock. */ | ||
523 | static void pcistub_remove(struct pci_dev *dev) | 536 | static void pcistub_remove(struct pci_dev *dev) |
524 | { | 537 | { |
525 | struct pcistub_device *psdev, *found_psdev = NULL; | 538 | struct pcistub_device *psdev, *found_psdev = NULL; |
@@ -551,6 +564,8 @@ static void pcistub_remove(struct pci_dev *dev) | |||
551 | pr_warn("****** shutdown driver domain before binding device\n"); | 564 | pr_warn("****** shutdown driver domain before binding device\n"); |
552 | pr_warn("****** to other drivers or domains\n"); | 565 | pr_warn("****** to other drivers or domains\n"); |
553 | 566 | ||
567 | /* N.B. This ends up calling pcistub_put_pci_dev which ends up | ||
568 | * doing the FLR. */ | ||
554 | xen_pcibk_release_pci_dev(found_psdev->pdev, | 569 | xen_pcibk_release_pci_dev(found_psdev->pdev, |
555 | found_psdev->dev); | 570 | found_psdev->dev); |
556 | } | 571 | } |
diff --git a/drivers/xen/xen-pciback/pciback_ops.c b/drivers/xen/xen-pciback/pciback_ops.c index 607e41460c0d..c4a0666de6f5 100644 --- a/drivers/xen/xen-pciback/pciback_ops.c +++ b/drivers/xen/xen-pciback/pciback_ops.c | |||
@@ -348,9 +348,9 @@ void xen_pcibk_do_op(struct work_struct *data) | |||
348 | notify_remote_via_irq(pdev->evtchn_irq); | 348 | notify_remote_via_irq(pdev->evtchn_irq); |
349 | 349 | ||
350 | /* Mark that we're done. */ | 350 | /* Mark that we're done. */ |
351 | smp_mb__before_clear_bit(); /* /after/ clearing PCIF_active */ | 351 | smp_mb__before_atomic(); /* /after/ clearing PCIF_active */ |
352 | clear_bit(_PDEVF_op_active, &pdev->flags); | 352 | clear_bit(_PDEVF_op_active, &pdev->flags); |
353 | smp_mb__after_clear_bit(); /* /before/ final check for work */ | 353 | smp_mb__after_atomic(); /* /before/ final check for work */ |
354 | 354 | ||
355 | /* Check to see if the driver domain tried to start another request in | 355 | /* Check to see if the driver domain tried to start another request in |
356 | * between clearing _XEN_PCIF_active and clearing _PDEVF_op_active. | 356 | * between clearing _XEN_PCIF_active and clearing _PDEVF_op_active. |
diff --git a/drivers/xen/xen-pciback/xenbus.c b/drivers/xen/xen-pciback/xenbus.c index a9ed867afaba..4a7e6e0a5f4c 100644 --- a/drivers/xen/xen-pciback/xenbus.c +++ b/drivers/xen/xen-pciback/xenbus.c | |||
@@ -93,6 +93,8 @@ static void free_pdev(struct xen_pcibk_device *pdev) | |||
93 | 93 | ||
94 | xen_pcibk_disconnect(pdev); | 94 | xen_pcibk_disconnect(pdev); |
95 | 95 | ||
96 | /* N.B. This calls pcistub_put_pci_dev which does the FLR on all | ||
97 | * of the PCIe devices. */ | ||
96 | xen_pcibk_release_devices(pdev); | 98 | xen_pcibk_release_devices(pdev); |
97 | 99 | ||
98 | dev_set_drvdata(&pdev->xdev->dev, NULL); | 100 | dev_set_drvdata(&pdev->xdev->dev, NULL); |
@@ -286,6 +288,8 @@ static int xen_pcibk_remove_device(struct xen_pcibk_device *pdev, | |||
286 | dev_dbg(&dev->dev, "unregistering for %d\n", pdev->xdev->otherend_id); | 288 | dev_dbg(&dev->dev, "unregistering for %d\n", pdev->xdev->otherend_id); |
287 | xen_unregister_device_domain_owner(dev); | 289 | xen_unregister_device_domain_owner(dev); |
288 | 290 | ||
291 | /* N.B. This ends up calling pcistub_put_pci_dev which ends up | ||
292 | * doing the FLR. */ | ||
289 | xen_pcibk_release_pci_dev(pdev, dev); | 293 | xen_pcibk_release_pci_dev(pdev, dev); |
290 | 294 | ||
291 | out: | 295 | out: |