Commit dce3ab4c authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'for-linus-6.15-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip

Pull xen updates from Juergen Gross:

 - cleanup: remove an used function

 - add support for a XenServer specific virtual PCI device

 - fix the handling of a sparse Xen hypervisor symbol table

 - avoid warnings when building the kernel with gcc 15

 - fix use of devices behind a VMD bridge when running as a Xen PV dom0

* tag 'for-linus-6.15-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip:
  PCI/MSI: Convert pci_msi_ignore_mask to per MSI domain flag
  PCI: vmd: Disable MSI remapping bypass under Xen
  xen/pci: Do not register devices with segments >= 0x10000
  xen/pciback: Remove unused pcistub_get_pci_dev
  xenfs/xensyms: respect hypervisor's "next" indication
  xen/mcelog: Add __nonstring annotations for unterminated strings
  xen: Add support for XenServer 6.1 platform device
parents edb0e8f6 c3164d2e
Loading
Loading
Loading
Loading
+2 −6
Original line number Diff line number Diff line
@@ -436,7 +436,8 @@ static struct msi_domain_ops xen_pci_msi_domain_ops = {
};

static struct msi_domain_info xen_pci_msi_domain_info = {
	.flags			= MSI_FLAG_PCI_MSIX | MSI_FLAG_FREE_MSI_DESCS | MSI_FLAG_DEV_SYSFS,
	.flags			= MSI_FLAG_PCI_MSIX | MSI_FLAG_FREE_MSI_DESCS |
				  MSI_FLAG_DEV_SYSFS | MSI_FLAG_NO_MASK,
	.ops			= &xen_pci_msi_domain_ops,
};

@@ -484,11 +485,6 @@ static __init void xen_setup_pci_msi(void)
	 * in allocating the native domain and never use it.
	 */
	x86_init.irqs.create_pci_msi_domain = xen_create_pci_msi_domain;
	/*
	 * With XEN PIRQ/Eventchannels in use PCI/MSI[-X] masking is solely
	 * controlled by the hypervisor.
	 */
	pci_msi_ignore_mask = 1;
}

#else /* CONFIG_PCI_MSI */
+20 −0
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@
#include <linux/rculist.h>
#include <linux/rcupdate.h>

#include <xen/xen.h>

#include <asm/irqdomain.h>

#define VMD_CFGBAR	0
@@ -970,6 +972,24 @@ static int vmd_probe(struct pci_dev *dev, const struct pci_device_id *id)
	struct vmd_dev *vmd;
	int err;

	if (xen_domain()) {
		/*
		 * Xen doesn't have knowledge about devices in the VMD bus
		 * because the config space of devices behind the VMD bridge is
		 * not known to Xen, and hence Xen cannot discover or configure
		 * them in any way.
		 *
		 * Bypass of MSI remapping won't work in that case as direct
		 * write by Linux to the MSI entries won't result in functional
		 * interrupts, as Xen is the entity that manages the host
		 * interrupt controller and must configure interrupts.  However
		 * multiplexing of interrupts by the VMD bridge will work under
		 * Xen, so force the usage of that mode which must always be
		 * supported by VMD bridges.
		 */
		features &= ~VMD_FEAT_CAN_BYPASS_MSI_REMAP;
	}

	if (resource_size(&dev->resource[VMD_CFGBAR]) < (1 << 20))
		return -ENOMEM;

+21 −16
Original line number Diff line number Diff line
@@ -10,12 +10,12 @@
#include <linux/err.h>
#include <linux/export.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>

#include "../pci.h"
#include "msi.h"

int pci_msi_enable = 1;
int pci_msi_ignore_mask;

/**
 * pci_msi_supported - check whether MSI may be enabled on a device
@@ -285,6 +285,8 @@ static void pci_msi_set_enable(struct pci_dev *dev, int enable)
static int msi_setup_msi_desc(struct pci_dev *dev, int nvec,
			      struct irq_affinity_desc *masks)
{
	const struct irq_domain *d = dev_get_msi_domain(&dev->dev);
	const struct msi_domain_info *info = d->host_data;
	struct msi_desc desc;
	u16 control;

@@ -295,8 +297,7 @@ static int msi_setup_msi_desc(struct pci_dev *dev, int nvec,
	/* Lies, damned lies, and MSIs */
	if (dev->dev_flags & PCI_DEV_FLAGS_HAS_MSI_MASKING)
		control |= PCI_MSI_FLAGS_MASKBIT;
	/* Respect XEN's mask disabling */
	if (pci_msi_ignore_mask)
	if (info->flags & MSI_FLAG_NO_MASK)
		control &= ~PCI_MSI_FLAGS_MASKBIT;

	desc.nvec_used			= nvec;
@@ -603,12 +604,15 @@ static void __iomem *msix_map_region(struct pci_dev *dev,
 */
void msix_prepare_msi_desc(struct pci_dev *dev, struct msi_desc *desc)
{
	const struct irq_domain *d = dev_get_msi_domain(&dev->dev);
	const struct msi_domain_info *info = d->host_data;

	desc->nvec_used				= 1;
	desc->pci.msi_attrib.is_msix		= 1;
	desc->pci.msi_attrib.is_64		= 1;
	desc->pci.msi_attrib.default_irq	= dev->irq;
	desc->pci.mask_base			= dev->msix_base;
	desc->pci.msi_attrib.can_mask		= !pci_msi_ignore_mask &&
	desc->pci.msi_attrib.can_mask		= !(info->flags & MSI_FLAG_NO_MASK) &&
						  !desc->pci.msi_attrib.is_virtual;

	if (desc->pci.msi_attrib.can_mask) {
@@ -658,9 +662,6 @@ static void msix_mask_all(void __iomem *base, int tsize)
	u32 ctrl = PCI_MSIX_ENTRY_CTRL_MASKBIT;
	int i;

	if (pci_msi_ignore_mask)
		return;

	for (i = 0; i < tsize; i++, base += PCI_MSIX_ENTRY_SIZE)
		writel(ctrl, base + PCI_MSIX_ENTRY_VECTOR_CTRL);
}
@@ -714,6 +715,8 @@ static int msix_setup_interrupts(struct pci_dev *dev, struct msix_entry *entries
static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries,
				int nvec, struct irq_affinity *affd)
{
	const struct irq_domain *d = dev_get_msi_domain(&dev->dev);
	const struct msi_domain_info *info = d->host_data;
	int ret, tsize;
	u16 control;

@@ -744,6 +747,7 @@ static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries,
	/* Disable INTX */
	pci_intx_for_msi(dev, 0);

	if (!(info->flags & MSI_FLAG_NO_MASK)) {
		/*
		 * Ensure that all table entries are masked to prevent
		 * stale entries from firing in a crash kernel.
@@ -753,6 +757,7 @@ static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries,
		 * when MSI-X is disabled, which prevents MSI delivery.
		 */
		msix_mask_all(dev->msix_base, tsize);
	}
	pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL, 0);

	pcibios_free_irq(dev);
+32 −0
Original line number Diff line number Diff line
@@ -43,6 +43,18 @@ static int xen_add_device(struct device *dev)
		pci_mcfg_reserved = true;
	}
#endif

	if (pci_domain_nr(pci_dev->bus) >> 16) {
		/*
		 * The hypercall interface is limited to 16bit PCI segment
		 * values, do not attempt to register devices with Xen in
		 * segments greater or equal than 0x10000.
		 */
		dev_info(dev,
			 "not registering with Xen: invalid PCI segment\n");
		return 0;
	}

	if (pci_seg_supported) {
		DEFINE_RAW_FLEX(struct physdev_pci_device_add, add, optarr, 1);

@@ -149,6 +161,16 @@ static int xen_remove_device(struct device *dev)
	int r;
	struct pci_dev *pci_dev = to_pci_dev(dev);

	if (pci_domain_nr(pci_dev->bus) >> 16) {
		/*
		 * The hypercall interface is limited to 16bit PCI segment
		 * values.
		 */
		dev_info(dev,
			 "not unregistering with Xen: invalid PCI segment\n");
		return 0;
	}

	if (pci_seg_supported) {
		struct physdev_pci_device device = {
			.seg = pci_domain_nr(pci_dev->bus),
@@ -182,6 +204,16 @@ int xen_reset_device(const struct pci_dev *dev)
		.flags = PCI_DEVICE_RESET_FLR,
	};

	if (pci_domain_nr(dev->bus) >> 16) {
		/*
		 * The hypercall interface is limited to 16bit PCI segment
		 * values.
		 */
		dev_info(&dev->dev,
			 "unable to notify Xen of device reset: invalid PCI segment\n");
		return 0;
	}

	return HYPERVISOR_physdev_op(PHYSDEVOP_pci_device_reset, &device);
}
EXPORT_SYMBOL_GPL(xen_reset_device);
+4 −0
Original line number Diff line number Diff line
@@ -26,6 +26,8 @@

#define DRV_NAME    "xen-platform-pci"

#define PCI_DEVICE_ID_XEN_PLATFORM_XS61	0x0002

static unsigned long platform_mmio;
static unsigned long platform_mmio_alloc;
static unsigned long platform_mmiolen;
@@ -174,6 +176,8 @@ static int platform_pci_probe(struct pci_dev *pdev,
static const struct pci_device_id platform_pci_tbl[] = {
	{PCI_VENDOR_ID_XEN, PCI_DEVICE_ID_XEN_PLATFORM,
		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
	{PCI_VENDOR_ID_XEN, PCI_DEVICE_ID_XEN_PLATFORM_XS61,
		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
	{0,}
};

Loading