diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-06 14:19:10 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-06 14:19:10 -0400 |
| commit | 541efb7632642cab55361178d73d544f025b593c (patch) | |
| tree | eee019bef6c95f50561ba4194ba0dba7b66a252b /drivers/xen | |
| parent | 6218590bcb452c3da7517d02b588d4d0a8628f73 (diff) | |
| parent | a6a198bc60e6c980a56eca24d33dc7f29139f8ea (diff) | |
Merge tag 'for-linus-4.9-rc0-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip
Pull xen updates from David Vrabel:
"xen features and fixes for 4.9:
- switch to new CPU hotplug mechanism
- support driver_override in pciback
- require vector callback for HVM guests (the alternate mechanism via
the platform device has been broken for ages)"
* tag 'for-linus-4.9-rc0-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip:
xen/x86: Update topology map for PV VCPUs
xen/x86: Initialize per_cpu(xen_vcpu, 0) a little earlier
xen/pciback: support driver_override
xen/pciback: avoid multiple entries in slot list
xen/pciback: simplify pcistub device handling
xen: Remove event channel notification through Xen PCI platform device
xen/events: Convert to hotplug state machine
xen/x86: Convert to hotplug state machine
x86/xen: add missing \n at end of printk warning message
xen/grant-table: Use kmalloc_array() in arch_gnttab_valloc()
xen: Make VPMU init message look less scary
xen: rename xen_pmu_init() in sys-hypervisor.c
hotplug: Prevent alloc/free of irq descriptors during cpu up/down (again)
xen/x86: Move irq allocation from Xen smp_op.cpu_up()
Diffstat (limited to 'drivers/xen')
| -rw-r--r-- | drivers/xen/events/events_base.c | 26 | ||||
| -rw-r--r-- | drivers/xen/events/events_fifo.c | 34 | ||||
| -rw-r--r-- | drivers/xen/platform-pci.c | 64 | ||||
| -rw-r--r-- | drivers/xen/sys-hypervisor.c | 12 | ||||
| -rw-r--r-- | drivers/xen/xen-pciback/pci_stub.c | 117 |
5 files changed, 108 insertions, 145 deletions
diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c index d5dbdb9d24d8..9ecfcdcdd6d6 100644 --- a/drivers/xen/events/events_base.c +++ b/drivers/xen/events/events_base.c | |||
| @@ -1314,9 +1314,6 @@ static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu) | |||
| 1314 | if (!VALID_EVTCHN(evtchn)) | 1314 | if (!VALID_EVTCHN(evtchn)) |
| 1315 | return -1; | 1315 | return -1; |
| 1316 | 1316 | ||
| 1317 | if (!xen_support_evtchn_rebind()) | ||
| 1318 | return -1; | ||
| 1319 | |||
| 1320 | /* Send future instances of this interrupt to other vcpu. */ | 1317 | /* Send future instances of this interrupt to other vcpu. */ |
| 1321 | bind_vcpu.port = evtchn; | 1318 | bind_vcpu.port = evtchn; |
| 1322 | bind_vcpu.vcpu = xen_vcpu_nr(tcpu); | 1319 | bind_vcpu.vcpu = xen_vcpu_nr(tcpu); |
| @@ -1650,20 +1647,15 @@ void xen_callback_vector(void) | |||
| 1650 | { | 1647 | { |
| 1651 | int rc; | 1648 | int rc; |
| 1652 | uint64_t callback_via; | 1649 | uint64_t callback_via; |
| 1653 | if (xen_have_vector_callback) { | 1650 | |
| 1654 | callback_via = HVM_CALLBACK_VECTOR(HYPERVISOR_CALLBACK_VECTOR); | 1651 | callback_via = HVM_CALLBACK_VECTOR(HYPERVISOR_CALLBACK_VECTOR); |
| 1655 | rc = xen_set_callback_via(callback_via); | 1652 | rc = xen_set_callback_via(callback_via); |
| 1656 | if (rc) { | 1653 | BUG_ON(rc); |
| 1657 | pr_err("Request for Xen HVM callback vector failed\n"); | 1654 | pr_info("Xen HVM callback vector for event delivery is enabled\n"); |
| 1658 | xen_have_vector_callback = 0; | 1655 | /* in the restore case the vector has already been allocated */ |
| 1659 | return; | 1656 | if (!test_bit(HYPERVISOR_CALLBACK_VECTOR, used_vectors)) |
| 1660 | } | 1657 | alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR, |
| 1661 | pr_info("Xen HVM callback vector for event delivery is enabled\n"); | 1658 | xen_hvm_callback_vector); |
| 1662 | /* in the restore case the vector has already been allocated */ | ||
| 1663 | if (!test_bit(HYPERVISOR_CALLBACK_VECTOR, used_vectors)) | ||
| 1664 | alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR, | ||
| 1665 | xen_hvm_callback_vector); | ||
| 1666 | } | ||
| 1667 | } | 1659 | } |
| 1668 | #else | 1660 | #else |
| 1669 | void xen_callback_vector(void) {} | 1661 | void xen_callback_vector(void) {} |
diff --git a/drivers/xen/events/events_fifo.c b/drivers/xen/events/events_fifo.c index 266c2c733039..7ef27c6ed72f 100644 --- a/drivers/xen/events/events_fifo.c +++ b/drivers/xen/events/events_fifo.c | |||
| @@ -418,30 +418,18 @@ static int evtchn_fifo_alloc_control_block(unsigned cpu) | |||
| 418 | return ret; | 418 | return ret; |
| 419 | } | 419 | } |
| 420 | 420 | ||
| 421 | static int evtchn_fifo_cpu_notification(struct notifier_block *self, | 421 | static int xen_evtchn_cpu_prepare(unsigned int cpu) |
| 422 | unsigned long action, | ||
| 423 | void *hcpu) | ||
| 424 | { | 422 | { |
| 425 | int cpu = (long)hcpu; | 423 | if (!per_cpu(cpu_control_block, cpu)) |
| 426 | int ret = 0; | 424 | return evtchn_fifo_alloc_control_block(cpu); |
| 427 | 425 | return 0; | |
| 428 | switch (action) { | ||
| 429 | case CPU_UP_PREPARE: | ||
| 430 | if (!per_cpu(cpu_control_block, cpu)) | ||
| 431 | ret = evtchn_fifo_alloc_control_block(cpu); | ||
| 432 | break; | ||
| 433 | case CPU_DEAD: | ||
| 434 | __evtchn_fifo_handle_events(cpu, true); | ||
| 435 | break; | ||
| 436 | default: | ||
| 437 | break; | ||
| 438 | } | ||
| 439 | return ret < 0 ? NOTIFY_BAD : NOTIFY_OK; | ||
| 440 | } | 426 | } |
| 441 | 427 | ||
| 442 | static struct notifier_block evtchn_fifo_cpu_notifier = { | 428 | static int xen_evtchn_cpu_dead(unsigned int cpu) |
| 443 | .notifier_call = evtchn_fifo_cpu_notification, | 429 | { |
| 444 | }; | 430 | __evtchn_fifo_handle_events(cpu, true); |
| 431 | return 0; | ||
| 432 | } | ||
| 445 | 433 | ||
| 446 | int __init xen_evtchn_fifo_init(void) | 434 | int __init xen_evtchn_fifo_init(void) |
| 447 | { | 435 | { |
| @@ -456,7 +444,9 @@ int __init xen_evtchn_fifo_init(void) | |||
| 456 | 444 | ||
| 457 | evtchn_ops = &evtchn_ops_fifo; | 445 | evtchn_ops = &evtchn_ops_fifo; |
| 458 | 446 | ||
| 459 | register_cpu_notifier(&evtchn_fifo_cpu_notifier); | 447 | cpuhp_setup_state_nocalls(CPUHP_XEN_EVTCHN_PREPARE, |
| 448 | "CPUHP_XEN_EVTCHN_PREPARE", | ||
| 449 | xen_evtchn_cpu_prepare, xen_evtchn_cpu_dead); | ||
| 460 | out: | 450 | out: |
| 461 | put_cpu(); | 451 | put_cpu(); |
| 462 | return ret; | 452 | return ret; |
diff --git a/drivers/xen/platform-pci.c b/drivers/xen/platform-pci.c index cf9666680c8c..b59c9455aae1 100644 --- a/drivers/xen/platform-pci.c +++ b/drivers/xen/platform-pci.c | |||
| @@ -42,7 +42,6 @@ | |||
| 42 | static unsigned long platform_mmio; | 42 | static unsigned long platform_mmio; |
| 43 | static unsigned long platform_mmio_alloc; | 43 | static unsigned long platform_mmio_alloc; |
| 44 | static unsigned long platform_mmiolen; | 44 | static unsigned long platform_mmiolen; |
| 45 | static uint64_t callback_via; | ||
| 46 | 45 | ||
| 47 | static unsigned long alloc_xen_mmio(unsigned long len) | 46 | static unsigned long alloc_xen_mmio(unsigned long len) |
| 48 | { | 47 | { |
| @@ -55,51 +54,6 @@ static unsigned long alloc_xen_mmio(unsigned long len) | |||
| 55 | return addr; | 54 | return addr; |
| 56 | } | 55 | } |
| 57 | 56 | ||
| 58 | static uint64_t get_callback_via(struct pci_dev *pdev) | ||
| 59 | { | ||
| 60 | u8 pin; | ||
| 61 | int irq; | ||
| 62 | |||
| 63 | irq = pdev->irq; | ||
| 64 | if (irq < 16) | ||
| 65 | return irq; /* ISA IRQ */ | ||
| 66 | |||
| 67 | pin = pdev->pin; | ||
| 68 | |||
| 69 | /* We don't know the GSI. Specify the PCI INTx line instead. */ | ||
| 70 | return ((uint64_t)0x01 << 56) | /* PCI INTx identifier */ | ||
| 71 | ((uint64_t)pci_domain_nr(pdev->bus) << 32) | | ||
| 72 | ((uint64_t)pdev->bus->number << 16) | | ||
| 73 | ((uint64_t)(pdev->devfn & 0xff) << 8) | | ||
| 74 | ((uint64_t)(pin - 1) & 3); | ||
| 75 | } | ||
| 76 | |||
| 77 | static irqreturn_t do_hvm_evtchn_intr(int irq, void *dev_id) | ||
| 78 | { | ||
| 79 | xen_hvm_evtchn_do_upcall(); | ||
| 80 | return IRQ_HANDLED; | ||
| 81 | } | ||
| 82 | |||
| 83 | static int xen_allocate_irq(struct pci_dev *pdev) | ||
| 84 | { | ||
| 85 | return request_irq(pdev->irq, do_hvm_evtchn_intr, | ||
| 86 | IRQF_NOBALANCING | IRQF_TRIGGER_RISING, | ||
| 87 | "xen-platform-pci", pdev); | ||
| 88 | } | ||
| 89 | |||
| 90 | static int platform_pci_resume(struct pci_dev *pdev) | ||
| 91 | { | ||
| 92 | int err; | ||
| 93 | if (xen_have_vector_callback) | ||
| 94 | return 0; | ||
| 95 | err = xen_set_callback_via(callback_via); | ||
| 96 | if (err) { | ||
| 97 | dev_err(&pdev->dev, "platform_pci_resume failure!\n"); | ||
| 98 | return err; | ||
| 99 | } | ||
| 100 | return 0; | ||
| 101 | } | ||
| 102 | |||
| 103 | static int platform_pci_probe(struct pci_dev *pdev, | 57 | static int platform_pci_probe(struct pci_dev *pdev, |
| 104 | const struct pci_device_id *ent) | 58 | const struct pci_device_id *ent) |
| 105 | { | 59 | { |
| @@ -138,21 +92,6 @@ static int platform_pci_probe(struct pci_dev *pdev, | |||
| 138 | platform_mmio = mmio_addr; | 92 | platform_mmio = mmio_addr; |
| 139 | platform_mmiolen = mmio_len; | 93 | platform_mmiolen = mmio_len; |
| 140 | 94 | ||
| 141 | if (!xen_have_vector_callback) { | ||
| 142 | ret = xen_allocate_irq(pdev); | ||
| 143 | if (ret) { | ||
| 144 | dev_warn(&pdev->dev, "request_irq failed err=%d\n", ret); | ||
| 145 | goto out; | ||
| 146 | } | ||
| 147 | callback_via = get_callback_via(pdev); | ||
| 148 | ret = xen_set_callback_via(callback_via); | ||
| 149 | if (ret) { | ||
| 150 | dev_warn(&pdev->dev, "Unable to set the evtchn callback " | ||
| 151 | "err=%d\n", ret); | ||
| 152 | goto out; | ||
| 153 | } | ||
| 154 | } | ||
| 155 | |||
| 156 | max_nr_gframes = gnttab_max_grant_frames(); | 95 | max_nr_gframes = gnttab_max_grant_frames(); |
| 157 | grant_frames = alloc_xen_mmio(PAGE_SIZE * max_nr_gframes); | 96 | grant_frames = alloc_xen_mmio(PAGE_SIZE * max_nr_gframes); |
| 158 | ret = gnttab_setup_auto_xlat_frames(grant_frames); | 97 | ret = gnttab_setup_auto_xlat_frames(grant_frames); |
| @@ -184,9 +123,6 @@ static struct pci_driver platform_driver = { | |||
| 184 | .name = DRV_NAME, | 123 | .name = DRV_NAME, |
| 185 | .probe = platform_pci_probe, | 124 | .probe = platform_pci_probe, |
| 186 | .id_table = platform_pci_tbl, | 125 | .id_table = platform_pci_tbl, |
| 187 | #ifdef CONFIG_PM | ||
| 188 | .resume_early = platform_pci_resume, | ||
| 189 | #endif | ||
| 190 | }; | 126 | }; |
| 191 | 127 | ||
| 192 | static int __init platform_pci_init(void) | 128 | static int __init platform_pci_init(void) |
diff --git a/drivers/xen/sys-hypervisor.c b/drivers/xen/sys-hypervisor.c index 6881b3ceb675..84106f9c456c 100644 --- a/drivers/xen/sys-hypervisor.c +++ b/drivers/xen/sys-hypervisor.c | |||
| @@ -215,7 +215,7 @@ static const struct attribute_group xen_compilation_group = { | |||
| 215 | .attrs = xen_compile_attrs, | 215 | .attrs = xen_compile_attrs, |
| 216 | }; | 216 | }; |
| 217 | 217 | ||
| 218 | static int __init xen_compilation_init(void) | 218 | static int __init xen_sysfs_compilation_init(void) |
| 219 | { | 219 | { |
| 220 | return sysfs_create_group(hypervisor_kobj, &xen_compilation_group); | 220 | return sysfs_create_group(hypervisor_kobj, &xen_compilation_group); |
| 221 | } | 221 | } |
| @@ -341,7 +341,7 @@ static const struct attribute_group xen_properties_group = { | |||
| 341 | .attrs = xen_properties_attrs, | 341 | .attrs = xen_properties_attrs, |
| 342 | }; | 342 | }; |
| 343 | 343 | ||
| 344 | static int __init xen_properties_init(void) | 344 | static int __init xen_sysfs_properties_init(void) |
| 345 | { | 345 | { |
| 346 | return sysfs_create_group(hypervisor_kobj, &xen_properties_group); | 346 | return sysfs_create_group(hypervisor_kobj, &xen_properties_group); |
| 347 | } | 347 | } |
| @@ -455,7 +455,7 @@ static const struct attribute_group xen_pmu_group = { | |||
| 455 | .attrs = xen_pmu_attrs, | 455 | .attrs = xen_pmu_attrs, |
| 456 | }; | 456 | }; |
| 457 | 457 | ||
| 458 | static int __init xen_pmu_init(void) | 458 | static int __init xen_sysfs_pmu_init(void) |
| 459 | { | 459 | { |
| 460 | return sysfs_create_group(hypervisor_kobj, &xen_pmu_group); | 460 | return sysfs_create_group(hypervisor_kobj, &xen_pmu_group); |
| 461 | } | 461 | } |
| @@ -474,18 +474,18 @@ static int __init hyper_sysfs_init(void) | |||
| 474 | ret = xen_sysfs_version_init(); | 474 | ret = xen_sysfs_version_init(); |
| 475 | if (ret) | 475 | if (ret) |
| 476 | goto version_out; | 476 | goto version_out; |
| 477 | ret = xen_compilation_init(); | 477 | ret = xen_sysfs_compilation_init(); |
| 478 | if (ret) | 478 | if (ret) |
| 479 | goto comp_out; | 479 | goto comp_out; |
| 480 | ret = xen_sysfs_uuid_init(); | 480 | ret = xen_sysfs_uuid_init(); |
| 481 | if (ret) | 481 | if (ret) |
| 482 | goto uuid_out; | 482 | goto uuid_out; |
| 483 | ret = xen_properties_init(); | 483 | ret = xen_sysfs_properties_init(); |
| 484 | if (ret) | 484 | if (ret) |
| 485 | goto prop_out; | 485 | goto prop_out; |
| 486 | #ifdef CONFIG_XEN_HAVE_VPMU | 486 | #ifdef CONFIG_XEN_HAVE_VPMU |
| 487 | if (xen_initial_domain()) { | 487 | if (xen_initial_domain()) { |
| 488 | ret = xen_pmu_init(); | 488 | ret = xen_sysfs_pmu_init(); |
| 489 | if (ret) { | 489 | if (ret) { |
| 490 | sysfs_remove_group(hypervisor_kobj, | 490 | sysfs_remove_group(hypervisor_kobj, |
| 491 | &xen_properties_group); | 491 | &xen_properties_group); |
diff --git a/drivers/xen/xen-pciback/pci_stub.c b/drivers/xen/xen-pciback/pci_stub.c index 258b7c325649..6331a95691a4 100644 --- a/drivers/xen/xen-pciback/pci_stub.c +++ b/drivers/xen/xen-pciback/pci_stub.c | |||
| @@ -25,6 +25,8 @@ | |||
| 25 | #include "conf_space.h" | 25 | #include "conf_space.h" |
| 26 | #include "conf_space_quirks.h" | 26 | #include "conf_space_quirks.h" |
| 27 | 27 | ||
| 28 | #define PCISTUB_DRIVER_NAME "pciback" | ||
| 29 | |||
| 28 | static char *pci_devs_to_hide; | 30 | static char *pci_devs_to_hide; |
| 29 | wait_queue_head_t xen_pcibk_aer_wait_queue; | 31 | wait_queue_head_t xen_pcibk_aer_wait_queue; |
| 30 | /*Add sem for sync AER handling and xen_pcibk remove/reconfigue ops, | 32 | /*Add sem for sync AER handling and xen_pcibk remove/reconfigue ops, |
| @@ -149,13 +151,10 @@ static inline void pcistub_device_put(struct pcistub_device *psdev) | |||
| 149 | kref_put(&psdev->kref, pcistub_device_release); | 151 | kref_put(&psdev->kref, pcistub_device_release); |
| 150 | } | 152 | } |
| 151 | 153 | ||
| 152 | static struct pcistub_device *pcistub_device_find(int domain, int bus, | 154 | static struct pcistub_device *pcistub_device_find_locked(int domain, int bus, |
| 153 | int slot, int func) | 155 | int slot, int func) |
| 154 | { | 156 | { |
| 155 | struct pcistub_device *psdev = NULL; | 157 | struct pcistub_device *psdev; |
| 156 | unsigned long flags; | ||
| 157 | |||
| 158 | spin_lock_irqsave(&pcistub_devices_lock, flags); | ||
| 159 | 158 | ||
| 160 | list_for_each_entry(psdev, &pcistub_devices, dev_list) { | 159 | list_for_each_entry(psdev, &pcistub_devices, dev_list) { |
| 161 | if (psdev->dev != NULL | 160 | if (psdev->dev != NULL |
| @@ -163,15 +162,25 @@ static struct pcistub_device *pcistub_device_find(int domain, int bus, | |||
| 163 | && bus == psdev->dev->bus->number | 162 | && bus == psdev->dev->bus->number |
| 164 | && slot == PCI_SLOT(psdev->dev->devfn) | 163 | && slot == PCI_SLOT(psdev->dev->devfn) |
| 165 | && func == PCI_FUNC(psdev->dev->devfn)) { | 164 | && func == PCI_FUNC(psdev->dev->devfn)) { |
| 166 | pcistub_device_get(psdev); | 165 | return psdev; |
| 167 | goto out; | ||
| 168 | } | 166 | } |
| 169 | } | 167 | } |
| 170 | 168 | ||
| 171 | /* didn't find it */ | 169 | return NULL; |
| 172 | psdev = NULL; | 170 | } |
| 171 | |||
| 172 | static struct pcistub_device *pcistub_device_find(int domain, int bus, | ||
| 173 | int slot, int func) | ||
| 174 | { | ||
| 175 | struct pcistub_device *psdev; | ||
| 176 | unsigned long flags; | ||
| 177 | |||
| 178 | spin_lock_irqsave(&pcistub_devices_lock, flags); | ||
| 179 | |||
| 180 | psdev = pcistub_device_find_locked(domain, bus, slot, func); | ||
| 181 | if (psdev) | ||
| 182 | pcistub_device_get(psdev); | ||
| 173 | 183 | ||
| 174 | out: | ||
| 175 | spin_unlock_irqrestore(&pcistub_devices_lock, flags); | 184 | spin_unlock_irqrestore(&pcistub_devices_lock, flags); |
| 176 | return psdev; | 185 | return psdev; |
| 177 | } | 186 | } |
| @@ -207,16 +216,9 @@ struct pci_dev *pcistub_get_pci_dev_by_slot(struct xen_pcibk_device *pdev, | |||
| 207 | 216 | ||
| 208 | spin_lock_irqsave(&pcistub_devices_lock, flags); | 217 | spin_lock_irqsave(&pcistub_devices_lock, flags); |
| 209 | 218 | ||
| 210 | list_for_each_entry(psdev, &pcistub_devices, dev_list) { | 219 | psdev = pcistub_device_find_locked(domain, bus, slot, func); |
| 211 | if (psdev->dev != NULL | 220 | if (psdev) |
| 212 | && domain == pci_domain_nr(psdev->dev->bus) | 221 | found_dev = pcistub_device_get_pci_dev(pdev, psdev); |
| 213 | && bus == psdev->dev->bus->number | ||
| 214 | && slot == PCI_SLOT(psdev->dev->devfn) | ||
| 215 | && func == PCI_FUNC(psdev->dev->devfn)) { | ||
| 216 | found_dev = pcistub_device_get_pci_dev(pdev, psdev); | ||
| 217 | break; | ||
| 218 | } | ||
| 219 | } | ||
| 220 | 222 | ||
| 221 | spin_unlock_irqrestore(&pcistub_devices_lock, flags); | 223 | spin_unlock_irqrestore(&pcistub_devices_lock, flags); |
| 222 | return found_dev; | 224 | return found_dev; |
| @@ -478,15 +480,48 @@ static int __init pcistub_init_devices_late(void) | |||
| 478 | return 0; | 480 | return 0; |
| 479 | } | 481 | } |
| 480 | 482 | ||
| 481 | static int pcistub_seize(struct pci_dev *dev) | 483 | static void pcistub_device_id_add_list(struct pcistub_device_id *new, |
| 484 | int domain, int bus, unsigned int devfn) | ||
| 485 | { | ||
| 486 | struct pcistub_device_id *pci_dev_id; | ||
| 487 | unsigned long flags; | ||
| 488 | int found = 0; | ||
| 489 | |||
| 490 | spin_lock_irqsave(&device_ids_lock, flags); | ||
| 491 | |||
| 492 | list_for_each_entry(pci_dev_id, &pcistub_device_ids, slot_list) { | ||
| 493 | if (pci_dev_id->domain == domain && pci_dev_id->bus == bus && | ||
| 494 | pci_dev_id->devfn == devfn) { | ||
| 495 | found = 1; | ||
| 496 | break; | ||
| 497 | } | ||
| 498 | } | ||
| 499 | |||
| 500 | if (!found) { | ||
| 501 | new->domain = domain; | ||
| 502 | new->bus = bus; | ||
| 503 | new->devfn = devfn; | ||
| 504 | list_add_tail(&new->slot_list, &pcistub_device_ids); | ||
| 505 | } | ||
| 506 | |||
| 507 | spin_unlock_irqrestore(&device_ids_lock, flags); | ||
| 508 | |||
| 509 | if (found) | ||
| 510 | kfree(new); | ||
| 511 | } | ||
| 512 | |||
| 513 | static int pcistub_seize(struct pci_dev *dev, | ||
| 514 | struct pcistub_device_id *pci_dev_id) | ||
| 482 | { | 515 | { |
| 483 | struct pcistub_device *psdev; | 516 | struct pcistub_device *psdev; |
| 484 | unsigned long flags; | 517 | unsigned long flags; |
| 485 | int err = 0; | 518 | int err = 0; |
| 486 | 519 | ||
| 487 | psdev = pcistub_device_alloc(dev); | 520 | psdev = pcistub_device_alloc(dev); |
| 488 | if (!psdev) | 521 | if (!psdev) { |
| 522 | kfree(pci_dev_id); | ||
| 489 | return -ENOMEM; | 523 | return -ENOMEM; |
| 524 | } | ||
| 490 | 525 | ||
| 491 | spin_lock_irqsave(&pcistub_devices_lock, flags); | 526 | spin_lock_irqsave(&pcistub_devices_lock, flags); |
| 492 | 527 | ||
| @@ -507,8 +542,12 @@ static int pcistub_seize(struct pci_dev *dev) | |||
| 507 | 542 | ||
| 508 | spin_unlock_irqrestore(&pcistub_devices_lock, flags); | 543 | spin_unlock_irqrestore(&pcistub_devices_lock, flags); |
| 509 | 544 | ||
| 510 | if (err) | 545 | if (err) { |
| 546 | kfree(pci_dev_id); | ||
| 511 | pcistub_device_put(psdev); | 547 | pcistub_device_put(psdev); |
| 548 | } else if (pci_dev_id) | ||
| 549 | pcistub_device_id_add_list(pci_dev_id, pci_domain_nr(dev->bus), | ||
| 550 | dev->bus->number, dev->devfn); | ||
| 512 | 551 | ||
| 513 | return err; | 552 | return err; |
| 514 | } | 553 | } |
| @@ -517,11 +556,16 @@ static int pcistub_seize(struct pci_dev *dev) | |||
| 517 | * other functions that take the sysfs lock. */ | 556 | * other functions that take the sysfs lock. */ |
| 518 | static int pcistub_probe(struct pci_dev *dev, const struct pci_device_id *id) | 557 | static int pcistub_probe(struct pci_dev *dev, const struct pci_device_id *id) |
| 519 | { | 558 | { |
| 520 | int err = 0; | 559 | int err = 0, match; |
| 560 | struct pcistub_device_id *pci_dev_id = NULL; | ||
| 521 | 561 | ||
| 522 | dev_dbg(&dev->dev, "probing...\n"); | 562 | dev_dbg(&dev->dev, "probing...\n"); |
| 523 | 563 | ||
| 524 | if (pcistub_match(dev)) { | 564 | match = pcistub_match(dev); |
| 565 | |||
| 566 | if ((dev->driver_override && | ||
| 567 | !strcmp(dev->driver_override, PCISTUB_DRIVER_NAME)) || | ||
| 568 | match) { | ||
| 525 | 569 | ||
| 526 | if (dev->hdr_type != PCI_HEADER_TYPE_NORMAL | 570 | if (dev->hdr_type != PCI_HEADER_TYPE_NORMAL |
| 527 | && dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) { | 571 | && dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) { |
| @@ -532,8 +576,16 @@ static int pcistub_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
| 532 | goto out; | 576 | goto out; |
| 533 | } | 577 | } |
| 534 | 578 | ||
| 579 | if (!match) { | ||
| 580 | pci_dev_id = kmalloc(sizeof(*pci_dev_id), GFP_ATOMIC); | ||
| 581 | if (!pci_dev_id) { | ||
| 582 | err = -ENOMEM; | ||
| 583 | goto out; | ||
| 584 | } | ||
| 585 | } | ||
| 586 | |||
| 535 | dev_info(&dev->dev, "seizing device\n"); | 587 | dev_info(&dev->dev, "seizing device\n"); |
| 536 | err = pcistub_seize(dev); | 588 | err = pcistub_seize(dev, pci_dev_id); |
| 537 | } else | 589 | } else |
| 538 | /* Didn't find the device */ | 590 | /* Didn't find the device */ |
| 539 | err = -ENODEV; | 591 | err = -ENODEV; |
| @@ -945,7 +997,7 @@ static const struct pci_error_handlers xen_pcibk_error_handler = { | |||
| 945 | static struct pci_driver xen_pcibk_pci_driver = { | 997 | static struct pci_driver xen_pcibk_pci_driver = { |
| 946 | /* The name should be xen_pciback, but until the tools are updated | 998 | /* The name should be xen_pciback, but until the tools are updated |
| 947 | * we will keep it as pciback. */ | 999 | * we will keep it as pciback. */ |
| 948 | .name = "pciback", | 1000 | .name = PCISTUB_DRIVER_NAME, |
| 949 | .id_table = pcistub_ids, | 1001 | .id_table = pcistub_ids, |
| 950 | .probe = pcistub_probe, | 1002 | .probe = pcistub_probe, |
| 951 | .remove = pcistub_remove, | 1003 | .remove = pcistub_remove, |
| @@ -1012,7 +1064,6 @@ static inline int str_to_quirk(const char *buf, int *domain, int *bus, int | |||
| 1012 | static int pcistub_device_id_add(int domain, int bus, int slot, int func) | 1064 | static int pcistub_device_id_add(int domain, int bus, int slot, int func) |
| 1013 | { | 1065 | { |
| 1014 | struct pcistub_device_id *pci_dev_id; | 1066 | struct pcistub_device_id *pci_dev_id; |
| 1015 | unsigned long flags; | ||
| 1016 | int rc = 0, devfn = PCI_DEVFN(slot, func); | 1067 | int rc = 0, devfn = PCI_DEVFN(slot, func); |
| 1017 | 1068 | ||
| 1018 | if (slot < 0) { | 1069 | if (slot < 0) { |
| @@ -1042,16 +1093,10 @@ static int pcistub_device_id_add(int domain, int bus, int slot, int func) | |||
| 1042 | if (!pci_dev_id) | 1093 | if (!pci_dev_id) |
| 1043 | return -ENOMEM; | 1094 | return -ENOMEM; |
| 1044 | 1095 | ||
| 1045 | pci_dev_id->domain = domain; | ||
| 1046 | pci_dev_id->bus = bus; | ||
| 1047 | pci_dev_id->devfn = devfn; | ||
| 1048 | |||
| 1049 | pr_debug("wants to seize %04x:%02x:%02x.%d\n", | 1096 | pr_debug("wants to seize %04x:%02x:%02x.%d\n", |
| 1050 | domain, bus, slot, func); | 1097 | domain, bus, slot, func); |
| 1051 | 1098 | ||
| 1052 | spin_lock_irqsave(&device_ids_lock, flags); | 1099 | pcistub_device_id_add_list(pci_dev_id, domain, bus, devfn); |
| 1053 | list_add_tail(&pci_dev_id->slot_list, &pcistub_device_ids); | ||
| 1054 | spin_unlock_irqrestore(&device_ids_lock, flags); | ||
| 1055 | 1100 | ||
| 1056 | return 0; | 1101 | return 0; |
| 1057 | } | 1102 | } |
