diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-06 21:19:10 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-06 21:19:10 +0300 |
commit | 541efb7632642cab55361178d73d544f025b593c (patch) | |
tree | eee019bef6c95f50561ba4194ba0dba7b66a252b /drivers/xen | |
parent | 6218590bcb452c3da7517d02b588d4d0a8628f73 (diff) | |
parent | a6a198bc60e6c980a56eca24d33dc7f29139f8ea (diff) | |
download | linux-541efb7632642cab55361178d73d544f025b593c.tar.xz |
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) if (!VALID_EVTCHN(evtchn)) return -1; - if (!xen_support_evtchn_rebind()) - return -1; - /* Send future instances of this interrupt to other vcpu. */ bind_vcpu.port = evtchn; bind_vcpu.vcpu = xen_vcpu_nr(tcpu); @@ -1650,20 +1647,15 @@ void xen_callback_vector(void) { int rc; uint64_t callback_via; - if (xen_have_vector_callback) { - callback_via = HVM_CALLBACK_VECTOR(HYPERVISOR_CALLBACK_VECTOR); - rc = xen_set_callback_via(callback_via); - if (rc) { - pr_err("Request for Xen HVM callback vector failed\n"); - xen_have_vector_callback = 0; - return; - } - pr_info("Xen HVM callback vector for event delivery is enabled\n"); - /* in the restore case the vector has already been allocated */ - if (!test_bit(HYPERVISOR_CALLBACK_VECTOR, used_vectors)) - alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR, - xen_hvm_callback_vector); - } + + callback_via = HVM_CALLBACK_VECTOR(HYPERVISOR_CALLBACK_VECTOR); + rc = xen_set_callback_via(callback_via); + BUG_ON(rc); + pr_info("Xen HVM callback vector for event delivery is enabled\n"); + /* in the restore case the vector has already been allocated */ + if (!test_bit(HYPERVISOR_CALLBACK_VECTOR, used_vectors)) + alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR, + xen_hvm_callback_vector); } #else 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) return ret; } -static int evtchn_fifo_cpu_notification(struct notifier_block *self, - unsigned long action, - void *hcpu) +static int xen_evtchn_cpu_prepare(unsigned int cpu) { - int cpu = (long)hcpu; - int ret = 0; - - switch (action) { - case CPU_UP_PREPARE: - if (!per_cpu(cpu_control_block, cpu)) - ret = evtchn_fifo_alloc_control_block(cpu); - break; - case CPU_DEAD: - __evtchn_fifo_handle_events(cpu, true); - break; - default: - break; - } - return ret < 0 ? NOTIFY_BAD : NOTIFY_OK; + if (!per_cpu(cpu_control_block, cpu)) + return evtchn_fifo_alloc_control_block(cpu); + return 0; } -static struct notifier_block evtchn_fifo_cpu_notifier = { - .notifier_call = evtchn_fifo_cpu_notification, -}; +static int xen_evtchn_cpu_dead(unsigned int cpu) +{ + __evtchn_fifo_handle_events(cpu, true); + return 0; +} int __init xen_evtchn_fifo_init(void) { @@ -456,7 +444,9 @@ int __init xen_evtchn_fifo_init(void) evtchn_ops = &evtchn_ops_fifo; - register_cpu_notifier(&evtchn_fifo_cpu_notifier); + cpuhp_setup_state_nocalls(CPUHP_XEN_EVTCHN_PREPARE, + "CPUHP_XEN_EVTCHN_PREPARE", + xen_evtchn_cpu_prepare, xen_evtchn_cpu_dead); out: put_cpu(); 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 @@ static unsigned long platform_mmio; static unsigned long platform_mmio_alloc; static unsigned long platform_mmiolen; -static uint64_t callback_via; static unsigned long alloc_xen_mmio(unsigned long len) { @@ -55,51 +54,6 @@ static unsigned long alloc_xen_mmio(unsigned long len) return addr; } -static uint64_t get_callback_via(struct pci_dev *pdev) -{ - u8 pin; - int irq; - - irq = pdev->irq; - if (irq < 16) - return irq; /* ISA IRQ */ - - pin = pdev->pin; - - /* We don't know the GSI. Specify the PCI INTx line instead. */ - return ((uint64_t)0x01 << 56) | /* PCI INTx identifier */ - ((uint64_t)pci_domain_nr(pdev->bus) << 32) | - ((uint64_t)pdev->bus->number << 16) | - ((uint64_t)(pdev->devfn & 0xff) << 8) | - ((uint64_t)(pin - 1) & 3); -} - -static irqreturn_t do_hvm_evtchn_intr(int irq, void *dev_id) -{ - xen_hvm_evtchn_do_upcall(); - return IRQ_HANDLED; -} - -static int xen_allocate_irq(struct pci_dev *pdev) -{ - return request_irq(pdev->irq, do_hvm_evtchn_intr, - IRQF_NOBALANCING | IRQF_TRIGGER_RISING, - "xen-platform-pci", pdev); -} - -static int platform_pci_resume(struct pci_dev *pdev) -{ - int err; - if (xen_have_vector_callback) - return 0; - err = xen_set_callback_via(callback_via); - if (err) { - dev_err(&pdev->dev, "platform_pci_resume failure!\n"); - return err; - } - return 0; -} - static int platform_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -138,21 +92,6 @@ static int platform_pci_probe(struct pci_dev *pdev, platform_mmio = mmio_addr; platform_mmiolen = mmio_len; - if (!xen_have_vector_callback) { - ret = xen_allocate_irq(pdev); - if (ret) { - dev_warn(&pdev->dev, "request_irq failed err=%d\n", ret); - goto out; - } - callback_via = get_callback_via(pdev); - ret = xen_set_callback_via(callback_via); - if (ret) { - dev_warn(&pdev->dev, "Unable to set the evtchn callback " - "err=%d\n", ret); - goto out; - } - } - max_nr_gframes = gnttab_max_grant_frames(); grant_frames = alloc_xen_mmio(PAGE_SIZE * max_nr_gframes); ret = gnttab_setup_auto_xlat_frames(grant_frames); @@ -184,9 +123,6 @@ static struct pci_driver platform_driver = { .name = DRV_NAME, .probe = platform_pci_probe, .id_table = platform_pci_tbl, -#ifdef CONFIG_PM - .resume_early = platform_pci_resume, -#endif }; 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 = { .attrs = xen_compile_attrs, }; -static int __init xen_compilation_init(void) +static int __init xen_sysfs_compilation_init(void) { return sysfs_create_group(hypervisor_kobj, &xen_compilation_group); } @@ -341,7 +341,7 @@ static const struct attribute_group xen_properties_group = { .attrs = xen_properties_attrs, }; -static int __init xen_properties_init(void) +static int __init xen_sysfs_properties_init(void) { return sysfs_create_group(hypervisor_kobj, &xen_properties_group); } @@ -455,7 +455,7 @@ static const struct attribute_group xen_pmu_group = { .attrs = xen_pmu_attrs, }; -static int __init xen_pmu_init(void) +static int __init xen_sysfs_pmu_init(void) { return sysfs_create_group(hypervisor_kobj, &xen_pmu_group); } @@ -474,18 +474,18 @@ static int __init hyper_sysfs_init(void) ret = xen_sysfs_version_init(); if (ret) goto version_out; - ret = xen_compilation_init(); + ret = xen_sysfs_compilation_init(); if (ret) goto comp_out; ret = xen_sysfs_uuid_init(); if (ret) goto uuid_out; - ret = xen_properties_init(); + ret = xen_sysfs_properties_init(); if (ret) goto prop_out; #ifdef CONFIG_XEN_HAVE_VPMU if (xen_initial_domain()) { - ret = xen_pmu_init(); + ret = xen_sysfs_pmu_init(); if (ret) { sysfs_remove_group(hypervisor_kobj, &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 @@ #include "conf_space.h" #include "conf_space_quirks.h" +#define PCISTUB_DRIVER_NAME "pciback" + static char *pci_devs_to_hide; wait_queue_head_t xen_pcibk_aer_wait_queue; /*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) kref_put(&psdev->kref, pcistub_device_release); } -static struct pcistub_device *pcistub_device_find(int domain, int bus, - int slot, int func) +static struct pcistub_device *pcistub_device_find_locked(int domain, int bus, + int slot, int func) { - struct pcistub_device *psdev = NULL; - unsigned long flags; - - spin_lock_irqsave(&pcistub_devices_lock, flags); + struct pcistub_device *psdev; list_for_each_entry(psdev, &pcistub_devices, dev_list) { if (psdev->dev != NULL @@ -163,15 +162,25 @@ static struct pcistub_device *pcistub_device_find(int domain, int bus, && bus == psdev->dev->bus->number && slot == PCI_SLOT(psdev->dev->devfn) && func == PCI_FUNC(psdev->dev->devfn)) { - pcistub_device_get(psdev); - goto out; + return psdev; } } - /* didn't find it */ - psdev = NULL; + return NULL; +} + +static struct pcistub_device *pcistub_device_find(int domain, int bus, + int slot, int func) +{ + struct pcistub_device *psdev; + unsigned long flags; + + spin_lock_irqsave(&pcistub_devices_lock, flags); + + psdev = pcistub_device_find_locked(domain, bus, slot, func); + if (psdev) + pcistub_device_get(psdev); -out: spin_unlock_irqrestore(&pcistub_devices_lock, flags); return psdev; } @@ -207,16 +216,9 @@ struct pci_dev *pcistub_get_pci_dev_by_slot(struct xen_pcibk_device *pdev, spin_lock_irqsave(&pcistub_devices_lock, flags); - list_for_each_entry(psdev, &pcistub_devices, dev_list) { - if (psdev->dev != NULL - && domain == pci_domain_nr(psdev->dev->bus) - && bus == psdev->dev->bus->number - && slot == PCI_SLOT(psdev->dev->devfn) - && func == PCI_FUNC(psdev->dev->devfn)) { - found_dev = pcistub_device_get_pci_dev(pdev, psdev); - break; - } - } + psdev = pcistub_device_find_locked(domain, bus, slot, func); + if (psdev) + found_dev = pcistub_device_get_pci_dev(pdev, psdev); spin_unlock_irqrestore(&pcistub_devices_lock, flags); return found_dev; @@ -478,15 +480,48 @@ static int __init pcistub_init_devices_late(void) return 0; } -static int pcistub_seize(struct pci_dev *dev) +static void pcistub_device_id_add_list(struct pcistub_device_id *new, + int domain, int bus, unsigned int devfn) +{ + struct pcistub_device_id *pci_dev_id; + unsigned long flags; + int found = 0; + + spin_lock_irqsave(&device_ids_lock, flags); + + list_for_each_entry(pci_dev_id, &pcistub_device_ids, slot_list) { + if (pci_dev_id->domain == domain && pci_dev_id->bus == bus && + pci_dev_id->devfn == devfn) { + found = 1; + break; + } + } + + if (!found) { + new->domain = domain; + new->bus = bus; + new->devfn = devfn; + list_add_tail(&new->slot_list, &pcistub_device_ids); + } + + spin_unlock_irqrestore(&device_ids_lock, flags); + + if (found) + kfree(new); +} + +static int pcistub_seize(struct pci_dev *dev, + struct pcistub_device_id *pci_dev_id) { struct pcistub_device *psdev; unsigned long flags; int err = 0; psdev = pcistub_device_alloc(dev); - if (!psdev) + if (!psdev) { + kfree(pci_dev_id); return -ENOMEM; + } spin_lock_irqsave(&pcistub_devices_lock, flags); @@ -507,8 +542,12 @@ static int pcistub_seize(struct pci_dev *dev) spin_unlock_irqrestore(&pcistub_devices_lock, flags); - if (err) + if (err) { + kfree(pci_dev_id); pcistub_device_put(psdev); + } else if (pci_dev_id) + pcistub_device_id_add_list(pci_dev_id, pci_domain_nr(dev->bus), + dev->bus->number, dev->devfn); return err; } @@ -517,11 +556,16 @@ static int pcistub_seize(struct pci_dev *dev) * other functions that take the sysfs lock. */ static int pcistub_probe(struct pci_dev *dev, const struct pci_device_id *id) { - int err = 0; + int err = 0, match; + struct pcistub_device_id *pci_dev_id = NULL; dev_dbg(&dev->dev, "probing...\n"); - if (pcistub_match(dev)) { + match = pcistub_match(dev); + + if ((dev->driver_override && + !strcmp(dev->driver_override, PCISTUB_DRIVER_NAME)) || + match) { if (dev->hdr_type != PCI_HEADER_TYPE_NORMAL && 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) goto out; } + if (!match) { + pci_dev_id = kmalloc(sizeof(*pci_dev_id), GFP_ATOMIC); + if (!pci_dev_id) { + err = -ENOMEM; + goto out; + } + } + dev_info(&dev->dev, "seizing device\n"); - err = pcistub_seize(dev); + err = pcistub_seize(dev, pci_dev_id); } else /* Didn't find the device */ err = -ENODEV; @@ -945,7 +997,7 @@ static const struct pci_error_handlers xen_pcibk_error_handler = { static struct pci_driver xen_pcibk_pci_driver = { /* The name should be xen_pciback, but until the tools are updated * we will keep it as pciback. */ - .name = "pciback", + .name = PCISTUB_DRIVER_NAME, .id_table = pcistub_ids, .probe = pcistub_probe, .remove = pcistub_remove, @@ -1012,7 +1064,6 @@ static inline int str_to_quirk(const char *buf, int *domain, int *bus, int static int pcistub_device_id_add(int domain, int bus, int slot, int func) { struct pcistub_device_id *pci_dev_id; - unsigned long flags; int rc = 0, devfn = PCI_DEVFN(slot, func); if (slot < 0) { @@ -1042,16 +1093,10 @@ static int pcistub_device_id_add(int domain, int bus, int slot, int func) if (!pci_dev_id) return -ENOMEM; - pci_dev_id->domain = domain; - pci_dev_id->bus = bus; - pci_dev_id->devfn = devfn; - pr_debug("wants to seize %04x:%02x:%02x.%d\n", domain, bus, slot, func); - spin_lock_irqsave(&device_ids_lock, flags); - list_add_tail(&pci_dev_id->slot_list, &pcistub_device_ids); - spin_unlock_irqrestore(&device_ids_lock, flags); + pcistub_device_id_add_list(pci_dev_id, domain, bus, devfn); return 0; } |