3b20eb23724d4 (Thomas Gleixner 2019-05-29 16:57:35 -0700 1) // SPDX-License-Identifier: GPL-2.0-only
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 2) /*
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 3) * Copyright (c) 2009, Intel Corporation.
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 4) *
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 5) * Author: Weidong Han <weidong.han@intel.com>
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 6) */
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 7)
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 8) #include <linux/pci.h>
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 9) #include <linux/acpi.h>
0b97b03d88b40 (Ross Lagerwall 2015-04-09 08:05:10 +0100 10) #include <linux/pci-acpi.h>
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 11) #include <xen/xen.h>
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 12) #include <xen/interface/physdev.h>
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 13) #include <xen/interface/xen.h>
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 14)
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 15) #include <asm/xen/hypervisor.h>
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 16) #include <asm/xen/hypercall.h>
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 17) #include "../pci/pci.h"
b7ef4a6dd35d1 (Ben Hutchings 2013-12-31 20:46:27 +0100 18) #ifdef CONFIG_PCI_MMCONFIG
8deb3eb1461e4 (Konrad Rzeszutek Wilk 2013-10-25 16:26:02 -0400 19) #include <asm/pci_x86.h>
a4098bc6eed5e (Igor Druzhinin 2019-09-12 19:31:51 +0100 20)
a4098bc6eed5e (Igor Druzhinin 2019-09-12 19:31:51 +0100 21) static int xen_mcfg_late(void);
b7ef4a6dd35d1 (Ben Hutchings 2013-12-31 20:46:27 +0100 22) #endif
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 23)
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 24) static bool __read_mostly pci_seg_supported = true;
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 25)
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 26) static int xen_add_device(struct device *dev)
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 27) {
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 28) int r;
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 29) struct pci_dev *pci_dev = to_pci_dev(dev);
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 30) #ifdef CONFIG_PCI_IOV
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 31) struct pci_dev *physfn = pci_dev->physfn;
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 32) #endif
a4098bc6eed5e (Igor Druzhinin 2019-09-12 19:31:51 +0100 33) #ifdef CONFIG_PCI_MMCONFIG
a4098bc6eed5e (Igor Druzhinin 2019-09-12 19:31:51 +0100 34) static bool pci_mcfg_reserved = false;
a4098bc6eed5e (Igor Druzhinin 2019-09-12 19:31:51 +0100 35) /*
a4098bc6eed5e (Igor Druzhinin 2019-09-12 19:31:51 +0100 36) * Reserve MCFG areas in Xen on first invocation due to this being
a4098bc6eed5e (Igor Druzhinin 2019-09-12 19:31:51 +0100 37) * potentially called from inside of acpi_init immediately after
a4098bc6eed5e (Igor Druzhinin 2019-09-12 19:31:51 +0100 38) * MCFG table has been finally parsed.
a4098bc6eed5e (Igor Druzhinin 2019-09-12 19:31:51 +0100 39) */
a4098bc6eed5e (Igor Druzhinin 2019-09-12 19:31:51 +0100 40) if (!pci_mcfg_reserved) {
a4098bc6eed5e (Igor Druzhinin 2019-09-12 19:31:51 +0100 41) xen_mcfg_late();
a4098bc6eed5e (Igor Druzhinin 2019-09-12 19:31:51 +0100 42) pci_mcfg_reserved = true;
a4098bc6eed5e (Igor Druzhinin 2019-09-12 19:31:51 +0100 43) }
a4098bc6eed5e (Igor Druzhinin 2019-09-12 19:31:51 +0100 44) #endif
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 45) if (pci_seg_supported) {
486edb24952c9 (Boris Ostrovsky 2014-08-04 18:17:23 -0400 46) struct {
486edb24952c9 (Boris Ostrovsky 2014-08-04 18:17:23 -0400 47) struct physdev_pci_device_add add;
486edb24952c9 (Boris Ostrovsky 2014-08-04 18:17:23 -0400 48) uint32_t pxm;
486edb24952c9 (Boris Ostrovsky 2014-08-04 18:17:23 -0400 49) } add_ext = {
486edb24952c9 (Boris Ostrovsky 2014-08-04 18:17:23 -0400 50) .add.seg = pci_domain_nr(pci_dev->bus),
486edb24952c9 (Boris Ostrovsky 2014-08-04 18:17:23 -0400 51) .add.bus = pci_dev->bus->number,
486edb24952c9 (Boris Ostrovsky 2014-08-04 18:17:23 -0400 52) .add.devfn = pci_dev->devfn
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 53) };
486edb24952c9 (Boris Ostrovsky 2014-08-04 18:17:23 -0400 54) struct physdev_pci_device_add *add = &add_ext.add;
486edb24952c9 (Boris Ostrovsky 2014-08-04 18:17:23 -0400 55)
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 56) #ifdef CONFIG_ACPI
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 57) acpi_handle handle;
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 58) #endif
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 59)
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 60) #ifdef CONFIG_PCI_IOV
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 61) if (pci_dev->is_virtfn) {
486edb24952c9 (Boris Ostrovsky 2014-08-04 18:17:23 -0400 62) add->flags = XEN_PCI_DEV_VIRTFN;
486edb24952c9 (Boris Ostrovsky 2014-08-04 18:17:23 -0400 63) add->physfn.bus = physfn->bus->number;
486edb24952c9 (Boris Ostrovsky 2014-08-04 18:17:23 -0400 64) add->physfn.devfn = physfn->devfn;
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 65) } else
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 66) #endif
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 67) if (pci_ari_enabled(pci_dev->bus) && PCI_SLOT(pci_dev->devfn))
486edb24952c9 (Boris Ostrovsky 2014-08-04 18:17:23 -0400 68) add->flags = XEN_PCI_DEV_EXTFN;
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 69)
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 70) #ifdef CONFIG_ACPI
3a83f992490f8 (Rafael J. Wysocki 2013-11-14 23:17:21 +0100 71) handle = ACPI_HANDLE(&pci_dev->dev);
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 72) #ifdef CONFIG_PCI_IOV
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 73) if (!handle && pci_dev->is_virtfn)
3a83f992490f8 (Rafael J. Wysocki 2013-11-14 23:17:21 +0100 74) handle = ACPI_HANDLE(physfn->bus->bridge);
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 75) #endif
0b97b03d88b40 (Ross Lagerwall 2015-04-09 08:05:10 +0100 76) if (!handle) {
0b97b03d88b40 (Ross Lagerwall 2015-04-09 08:05:10 +0100 77) /*
0b97b03d88b40 (Ross Lagerwall 2015-04-09 08:05:10 +0100 78) * This device was not listed in the ACPI name space at
0b97b03d88b40 (Ross Lagerwall 2015-04-09 08:05:10 +0100 79) * all. Try to get acpi handle of parent pci bus.
0b97b03d88b40 (Ross Lagerwall 2015-04-09 08:05:10 +0100 80) */
0b97b03d88b40 (Ross Lagerwall 2015-04-09 08:05:10 +0100 81) struct pci_bus *pbus;
0b97b03d88b40 (Ross Lagerwall 2015-04-09 08:05:10 +0100 82) for (pbus = pci_dev->bus; pbus; pbus = pbus->parent) {
0b97b03d88b40 (Ross Lagerwall 2015-04-09 08:05:10 +0100 83) handle = acpi_pci_get_bridge_handle(pbus);
0b97b03d88b40 (Ross Lagerwall 2015-04-09 08:05:10 +0100 84) if (handle)
0b97b03d88b40 (Ross Lagerwall 2015-04-09 08:05:10 +0100 85) break;
0b97b03d88b40 (Ross Lagerwall 2015-04-09 08:05:10 +0100 86) }
0b97b03d88b40 (Ross Lagerwall 2015-04-09 08:05:10 +0100 87) }
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 88) if (handle) {
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 89) acpi_status status;
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 90)
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 91) do {
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 92) unsigned long long pxm;
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 93)
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 94) status = acpi_evaluate_integer(handle, "_PXM",
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 95) NULL, &pxm);
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 96) if (ACPI_SUCCESS(status)) {
486edb24952c9 (Boris Ostrovsky 2014-08-04 18:17:23 -0400 97) add->optarr[0] = pxm;
486edb24952c9 (Boris Ostrovsky 2014-08-04 18:17:23 -0400 98) add->flags |= XEN_PCI_DEV_PXM;
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 99) break;
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 100) }
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 101) status = acpi_get_parent(handle, &handle);
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 102) } while (ACPI_SUCCESS(status));
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 103) }
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 104) #endif /* CONFIG_ACPI */
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 105)
486edb24952c9 (Boris Ostrovsky 2014-08-04 18:17:23 -0400 106) r = HYPERVISOR_physdev_op(PHYSDEVOP_pci_device_add, add);
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 107) if (r != -ENOSYS)
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 108) return r;
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 109) pci_seg_supported = false;
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 110) }
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 111)
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 112) if (pci_domain_nr(pci_dev->bus))
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 113) r = -ENOSYS;
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 114) #ifdef CONFIG_PCI_IOV
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 115) else if (pci_dev->is_virtfn) {
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 116) struct physdev_manage_pci_ext manage_pci_ext = {
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 117) .bus = pci_dev->bus->number,
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 118) .devfn = pci_dev->devfn,
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 119) .is_virtfn = 1,
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 120) .physfn.bus = physfn->bus->number,
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 121) .physfn.devfn = physfn->devfn,
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 122) };
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 123)
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 124) r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_add_ext,
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 125) &manage_pci_ext);
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 126) }
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 127) #endif
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 128) else if (pci_ari_enabled(pci_dev->bus) && PCI_SLOT(pci_dev->devfn)) {
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 129) struct physdev_manage_pci_ext manage_pci_ext = {
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 130) .bus = pci_dev->bus->number,
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 131) .devfn = pci_dev->devfn,
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 132) .is_extfn = 1,
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 133) };
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 134)
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 135) r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_add_ext,
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 136) &manage_pci_ext);
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 137) } else {
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 138) struct physdev_manage_pci manage_pci = {
4b0109830842f (Ruslan Pisarev 2011-07-26 14:16:38 +0300 139) .bus = pci_dev->bus->number,
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 140) .devfn = pci_dev->devfn,
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 141) };
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 142)
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 143) r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_add,
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 144) &manage_pci);
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 145) }
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 146)
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 147) return r;
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 148) }
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 149)
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 150) static int xen_remove_device(struct device *dev)
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 151) {
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 152) int r;
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 153) struct pci_dev *pci_dev = to_pci_dev(dev);
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 154)
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 155) if (pci_seg_supported) {
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 156) struct physdev_pci_device device = {
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 157) .seg = pci_domain_nr(pci_dev->bus),
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 158) .bus = pci_dev->bus->number,
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 159) .devfn = pci_dev->devfn
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 160) };
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 161)
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 162) r = HYPERVISOR_physdev_op(PHYSDEVOP_pci_device_remove,
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 163) &device);
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 164) } else if (pci_domain_nr(pci_dev->bus))
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 165) r = -ENOSYS;
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 166) else {
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 167) struct physdev_manage_pci manage_pci = {
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 168) .bus = pci_dev->bus->number,
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 169) .devfn = pci_dev->devfn
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 170) };
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 171)
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 172) r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_remove,
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 173) &manage_pci);
55e901fc1f03d (Jan Beulich 2011-09-22 09:17:57 +0100 174) }
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 175)
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 176) return r;
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 177) }
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 178)
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 179) static int xen_pci_notifier(struct notifier_block *nb,
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 180) unsigned long action, void *data)
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 181) {
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 182) struct device *dev = data;
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 183) int r = 0;
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 184)
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 185) switch (action) {
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 186) case BUS_NOTIFY_ADD_DEVICE:
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 187) r = xen_add_device(dev);
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 188) break;
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 189) case BUS_NOTIFY_DEL_DEVICE:
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 190) r = xen_remove_device(dev);
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 191) break;
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 192) default:
12e13ac84ca70 (Jan Beulich 2011-08-17 09:32:32 +0100 193) return NOTIFY_DONE;
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 194) }
12e13ac84ca70 (Jan Beulich 2011-08-17 09:32:32 +0100 195) if (r)
12e13ac84ca70 (Jan Beulich 2011-08-17 09:32:32 +0100 196) dev_err(dev, "Failed to %s - passthrough or MSI/MSI-X might fail!\n",
12e13ac84ca70 (Jan Beulich 2011-08-17 09:32:32 +0100 197) action == BUS_NOTIFY_ADD_DEVICE ? "add" :
12e13ac84ca70 (Jan Beulich 2011-08-17 09:32:32 +0100 198) (action == BUS_NOTIFY_DEL_DEVICE ? "delete" : "?"));
12e13ac84ca70 (Jan Beulich 2011-08-17 09:32:32 +0100 199) return NOTIFY_OK;
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 200) }
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 201)
12e13ac84ca70 (Jan Beulich 2011-08-17 09:32:32 +0100 202) static struct notifier_block device_nb = {
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 203) .notifier_call = xen_pci_notifier,
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 204) };
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 205)
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 206) static int __init register_xen_pci_notifier(void)
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 207) {
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 208) if (!xen_initial_domain())
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 209) return 0;
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 210)
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 211) return bus_register_notifier(&pci_bus_type, &device_nb);
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 212) }
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 213)
e28c31a96b157 (Weidong Han 2010-10-27 17:55:04 +0100 214) arch_initcall(register_xen_pci_notifier);
8deb3eb1461e4 (Konrad Rzeszutek Wilk 2013-10-25 16:26:02 -0400 215)
8deb3eb1461e4 (Konrad Rzeszutek Wilk 2013-10-25 16:26:02 -0400 216) #ifdef CONFIG_PCI_MMCONFIG
a4098bc6eed5e (Igor Druzhinin 2019-09-12 19:31:51 +0100 217) static int xen_mcfg_late(void)
8deb3eb1461e4 (Konrad Rzeszutek Wilk 2013-10-25 16:26:02 -0400 218) {
8deb3eb1461e4 (Konrad Rzeszutek Wilk 2013-10-25 16:26:02 -0400 219) struct pci_mmcfg_region *cfg;
8deb3eb1461e4 (Konrad Rzeszutek Wilk 2013-10-25 16:26:02 -0400 220) int rc;
8deb3eb1461e4 (Konrad Rzeszutek Wilk 2013-10-25 16:26:02 -0400 221)
8deb3eb1461e4 (Konrad Rzeszutek Wilk 2013-10-25 16:26:02 -0400 222) if (!xen_initial_domain())
8deb3eb1461e4 (Konrad Rzeszutek Wilk 2013-10-25 16:26:02 -0400 223) return 0;
8deb3eb1461e4 (Konrad Rzeszutek Wilk 2013-10-25 16:26:02 -0400 224)
8deb3eb1461e4 (Konrad Rzeszutek Wilk 2013-10-25 16:26:02 -0400 225) if ((pci_probe & PCI_PROBE_MMCONF) == 0)
8deb3eb1461e4 (Konrad Rzeszutek Wilk 2013-10-25 16:26:02 -0400 226) return 0;
8deb3eb1461e4 (Konrad Rzeszutek Wilk 2013-10-25 16:26:02 -0400 227)
8deb3eb1461e4 (Konrad Rzeszutek Wilk 2013-10-25 16:26:02 -0400 228) if (list_empty(&pci_mmcfg_list))
8deb3eb1461e4 (Konrad Rzeszutek Wilk 2013-10-25 16:26:02 -0400 229) return 0;
8deb3eb1461e4 (Konrad Rzeszutek Wilk 2013-10-25 16:26:02 -0400 230)
8deb3eb1461e4 (Konrad Rzeszutek Wilk 2013-10-25 16:26:02 -0400 231) /* Check whether they are in the right area. */
8deb3eb1461e4 (Konrad Rzeszutek Wilk 2013-10-25 16:26:02 -0400 232) list_for_each_entry(cfg, &pci_mmcfg_list, list) {
8deb3eb1461e4 (Konrad Rzeszutek Wilk 2013-10-25 16:26:02 -0400 233) struct physdev_pci_mmcfg_reserved r;
8deb3eb1461e4 (Konrad Rzeszutek Wilk 2013-10-25 16:26:02 -0400 234)
8deb3eb1461e4 (Konrad Rzeszutek Wilk 2013-10-25 16:26:02 -0400 235) r.address = cfg->address;
8deb3eb1461e4 (Konrad Rzeszutek Wilk 2013-10-25 16:26:02 -0400 236) r.segment = cfg->segment;
8deb3eb1461e4 (Konrad Rzeszutek Wilk 2013-10-25 16:26:02 -0400 237) r.start_bus = cfg->start_bus;
8deb3eb1461e4 (Konrad Rzeszutek Wilk 2013-10-25 16:26:02 -0400 238) r.end_bus = cfg->end_bus;
8deb3eb1461e4 (Konrad Rzeszutek Wilk 2013-10-25 16:26:02 -0400 239) r.flags = XEN_PCI_MMCFG_RESERVED;
8deb3eb1461e4 (Konrad Rzeszutek Wilk 2013-10-25 16:26:02 -0400 240)
8deb3eb1461e4 (Konrad Rzeszutek Wilk 2013-10-25 16:26:02 -0400 241) rc = HYPERVISOR_physdev_op(PHYSDEVOP_pci_mmcfg_reserved, &r);
8deb3eb1461e4 (Konrad Rzeszutek Wilk 2013-10-25 16:26:02 -0400 242) switch (rc) {
8deb3eb1461e4 (Konrad Rzeszutek Wilk 2013-10-25 16:26:02 -0400 243) case 0:
8deb3eb1461e4 (Konrad Rzeszutek Wilk 2013-10-25 16:26:02 -0400 244) case -ENOSYS:
8deb3eb1461e4 (Konrad Rzeszutek Wilk 2013-10-25 16:26:02 -0400 245) continue;
8deb3eb1461e4 (Konrad Rzeszutek Wilk 2013-10-25 16:26:02 -0400 246)
8deb3eb1461e4 (Konrad Rzeszutek Wilk 2013-10-25 16:26:02 -0400 247) default:
8deb3eb1461e4 (Konrad Rzeszutek Wilk 2013-10-25 16:26:02 -0400 248) pr_warn("Failed to report MMCONFIG reservation"
8deb3eb1461e4 (Konrad Rzeszutek Wilk 2013-10-25 16:26:02 -0400 249) " state for %s to hypervisor"
8deb3eb1461e4 (Konrad Rzeszutek Wilk 2013-10-25 16:26:02 -0400 250) " (%d)\n",
8deb3eb1461e4 (Konrad Rzeszutek Wilk 2013-10-25 16:26:02 -0400 251) cfg->name, rc);
8deb3eb1461e4 (Konrad Rzeszutek Wilk 2013-10-25 16:26:02 -0400 252) }
8deb3eb1461e4 (Konrad Rzeszutek Wilk 2013-10-25 16:26:02 -0400 253) }
8deb3eb1461e4 (Konrad Rzeszutek Wilk 2013-10-25 16:26:02 -0400 254) return 0;
8deb3eb1461e4 (Konrad Rzeszutek Wilk 2013-10-25 16:26:02 -0400 255) }
8deb3eb1461e4 (Konrad Rzeszutek Wilk 2013-10-25 16:26:02 -0400 256) #endif