Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 264466
b: refs/heads/master
c: 55e901f
h: refs/heads/master
v: v3
  • Loading branch information
Jan Beulich authored and Konrad Rzeszutek Wilk committed Sep 22, 2011
1 parent e3c24ac commit 61c83b7
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 15 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 6810df88dcfc22de267caf23eb072ffb97b3c411
refs/heads/master: 55e901fc1f03dd8437f877813c68b6014cdbeefd
22 changes: 19 additions & 3 deletions trunk/arch/x86/pci/xen.c
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,8 @@ static void xen_teardown_msi_irq(unsigned int irq)
}

#ifdef CONFIG_XEN_DOM0
static bool __read_mostly pci_seg_supported = true;

static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
{
int ret = 0;
Expand All @@ -202,10 +204,11 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)

memset(&map_irq, 0, sizeof(map_irq));
map_irq.domid = domid;
map_irq.type = MAP_PIRQ_TYPE_MSI;
map_irq.type = MAP_PIRQ_TYPE_MSI_SEG;
map_irq.index = -1;
map_irq.pirq = -1;
map_irq.bus = dev->bus->number;
map_irq.bus = dev->bus->number |
(pci_domain_nr(dev->bus) << 16);
map_irq.devfn = dev->devfn;

if (type == PCI_CAP_ID_MSIX) {
Expand All @@ -222,7 +225,20 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
map_irq.entry_nr = msidesc->msi_attrib.entry_nr;
}

ret = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq);
ret = -EINVAL;
if (pci_seg_supported)
ret = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq,
&map_irq);
if (ret == -EINVAL && !pci_domain_nr(dev->bus)) {
map_irq.type = MAP_PIRQ_TYPE_MSI;
map_irq.index = -1;
map_irq.pirq = -1;
map_irq.bus = dev->bus->number;
ret = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq,
&map_irq);
if (ret != -EINVAL)
pci_seg_supported = false;
}
if (ret) {
dev_warn(&dev->dev, "xen map irq failed %d for %d domain\n",
ret, domid);
Expand Down
94 changes: 84 additions & 10 deletions trunk/drivers/xen/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/

#include <linux/pci.h>
#include <linux/acpi.h>
#include <xen/xen.h>
#include <xen/interface/physdev.h>
#include <xen/interface/xen.h>
Expand All @@ -26,26 +27,85 @@
#include <asm/xen/hypercall.h>
#include "../pci/pci.h"

static bool __read_mostly pci_seg_supported = true;

static int xen_add_device(struct device *dev)
{
int r;
struct pci_dev *pci_dev = to_pci_dev(dev);
#ifdef CONFIG_PCI_IOV
struct pci_dev *physfn = pci_dev->physfn;
#endif

if (pci_seg_supported) {
struct physdev_pci_device_add add = {
.seg = pci_domain_nr(pci_dev->bus),
.bus = pci_dev->bus->number,
.devfn = pci_dev->devfn
};
#ifdef CONFIG_ACPI
acpi_handle handle;
#endif

#ifdef CONFIG_PCI_IOV
if (pci_dev->is_virtfn) {
if (pci_dev->is_virtfn) {
add.flags = XEN_PCI_DEV_VIRTFN;
add.physfn.bus = physfn->bus->number;
add.physfn.devfn = physfn->devfn;
} else
#endif
if (pci_ari_enabled(pci_dev->bus) && PCI_SLOT(pci_dev->devfn))
add.flags = XEN_PCI_DEV_EXTFN;

#ifdef CONFIG_ACPI
handle = DEVICE_ACPI_HANDLE(&pci_dev->dev);
if (!handle)
handle = DEVICE_ACPI_HANDLE(pci_dev->bus->bridge);
#ifdef CONFIG_PCI_IOV
if (!handle && pci_dev->is_virtfn)
handle = DEVICE_ACPI_HANDLE(physfn->bus->bridge);
#endif
if (handle) {
acpi_status status;

do {
unsigned long long pxm;

status = acpi_evaluate_integer(handle, "_PXM",
NULL, &pxm);
if (ACPI_SUCCESS(status)) {
add.optarr[0] = pxm;
add.flags |= XEN_PCI_DEV_PXM;
break;
}
status = acpi_get_parent(handle, &handle);
} while (ACPI_SUCCESS(status));
}
#endif /* CONFIG_ACPI */

r = HYPERVISOR_physdev_op(PHYSDEVOP_pci_device_add, &add);
if (r != -ENOSYS)
return r;
pci_seg_supported = false;
}

if (pci_domain_nr(pci_dev->bus))
r = -ENOSYS;
#ifdef CONFIG_PCI_IOV
else if (pci_dev->is_virtfn) {
struct physdev_manage_pci_ext manage_pci_ext = {
.bus = pci_dev->bus->number,
.devfn = pci_dev->devfn,
.is_virtfn = 1,
.physfn.bus = pci_dev->physfn->bus->number,
.physfn.devfn = pci_dev->physfn->devfn,
.physfn.bus = physfn->bus->number,
.physfn.devfn = physfn->devfn,
};

r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_add_ext,
&manage_pci_ext);
} else
}
#endif
if (pci_ari_enabled(pci_dev->bus) && PCI_SLOT(pci_dev->devfn)) {
else if (pci_ari_enabled(pci_dev->bus) && PCI_SLOT(pci_dev->devfn)) {
struct physdev_manage_pci_ext manage_pci_ext = {
.bus = pci_dev->bus->number,
.devfn = pci_dev->devfn,
Expand All @@ -71,13 +131,27 @@ static int xen_remove_device(struct device *dev)
{
int r;
struct pci_dev *pci_dev = to_pci_dev(dev);
struct physdev_manage_pci manage_pci;

manage_pci.bus = pci_dev->bus->number;
manage_pci.devfn = pci_dev->devfn;
if (pci_seg_supported) {
struct physdev_pci_device device = {
.seg = pci_domain_nr(pci_dev->bus),
.bus = pci_dev->bus->number,
.devfn = pci_dev->devfn
};

r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_remove,
&manage_pci);
r = HYPERVISOR_physdev_op(PHYSDEVOP_pci_device_remove,
&device);
} else if (pci_domain_nr(pci_dev->bus))
r = -ENOSYS;
else {
struct physdev_manage_pci manage_pci = {
.bus = pci_dev->bus->number,
.devfn = pci_dev->devfn
};

r = HYPERVISOR_physdev_op(PHYSDEVOP_manage_pci_remove,
&manage_pci);
}

return r;
}
Expand Down
34 changes: 33 additions & 1 deletion trunk/include/xen/interface/physdev.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ struct physdev_irq {
#define MAP_PIRQ_TYPE_MSI 0x0
#define MAP_PIRQ_TYPE_GSI 0x1
#define MAP_PIRQ_TYPE_UNKNOWN 0x2
#define MAP_PIRQ_TYPE_MSI_SEG 0x3

#define PHYSDEVOP_map_pirq 13
struct physdev_map_pirq {
Expand All @@ -119,7 +120,7 @@ struct physdev_map_pirq {
int index;
/* IN or OUT */
int pirq;
/* IN */
/* IN - high 16 bits hold segment for MAP_PIRQ_TYPE_MSI_SEG */
int bus;
/* IN */
int devfn;
Expand Down Expand Up @@ -198,6 +199,37 @@ struct physdev_get_free_pirq {
uint32_t pirq;
};

#define XEN_PCI_DEV_EXTFN 0x1
#define XEN_PCI_DEV_VIRTFN 0x2
#define XEN_PCI_DEV_PXM 0x4

#define PHYSDEVOP_pci_device_add 25
struct physdev_pci_device_add {
/* IN */
uint16_t seg;
uint8_t bus;
uint8_t devfn;
uint32_t flags;
struct {
uint8_t bus;
uint8_t devfn;
} physfn;
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
uint32_t optarr[];
#elif defined(__GNUC__)
uint32_t optarr[0];
#endif
};

#define PHYSDEVOP_pci_device_remove 26
#define PHYSDEVOP_restore_msi_ext 27
struct physdev_pci_device {
/* IN */
uint16_t seg;
uint8_t bus;
uint8_t devfn;
};

/*
* Notify that some PIRQ-bound event channels have been unmasked.
* ** This command is obsolete since interface version 0x00030202 and is **
Expand Down

0 comments on commit 61c83b7

Please sign in to comment.