Commit 04dcc048 authored by Bjorn Helgaas's avatar Bjorn Helgaas
Browse files

Merge branch 'remotes/lorenzo/pci/vmd'

- Program IRTE with Requester ID of VMD endpoint, not child device (Jon
  Derrick)

- Disable VMD MSI-X remapping when possible so children can use more MSI-X
  vectors (Jon Derrick)

* remotes/lorenzo/pci/vmd:
  PCI: vmd: Disable MSI-X remapping when possible
  iommu/vt-d: Use Real PCI DMA device for IRTE
parents 5b8dafa1 ee81ee84
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -1280,7 +1280,8 @@ static void intel_irq_remapping_prepare_irte(struct intel_ir_data *data,
		break;
	case X86_IRQ_ALLOC_TYPE_PCI_MSI:
	case X86_IRQ_ALLOC_TYPE_PCI_MSIX:
		set_msi_sid(irte, msi_desc_to_pci_dev(info->desc));
		set_msi_sid(irte,
			    pci_real_dma_dev(msi_desc_to_pci_dev(info->desc)));
		break;
	default:
		BUG_ON(1);
+51 −12
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@
#define BUS_RESTRICT_CAP(vmcap)	(vmcap & 0x1)
#define PCI_REG_VMCONFIG	0x44
#define BUS_RESTRICT_CFG(vmcfg)	((vmcfg >> 8) & 0x3)
#define VMCONFIG_MSI_REMAP	0x2
#define PCI_REG_VMLOCK		0x70
#define MB2_SHADOW_EN(vmlock)	(vmlock & 0x2)

@@ -59,6 +60,13 @@ enum vmd_features {
	 * be used for MSI remapping
	 */
	VMD_FEAT_OFFSET_FIRST_VECTOR		= (1 << 3),

	/*
	 * Device can bypass remapping MSI-X transactions into its MSI-X table,
	 * avoiding the requirement of a VMD MSI domain for child device
	 * interrupt handling.
	 */
	VMD_FEAT_CAN_BYPASS_MSI_REMAP		= (1 << 4),
};

/*
@@ -306,6 +314,16 @@ static struct msi_domain_info vmd_msi_domain_info = {
	.chip		= &vmd_msi_controller,
};

static void vmd_set_msi_remapping(struct vmd_dev *vmd, bool enable)
{
	u16 reg;

	pci_read_config_word(vmd->dev, PCI_REG_VMCONFIG, &reg);
	reg = enable ? (reg & ~VMCONFIG_MSI_REMAP) :
		       (reg | VMCONFIG_MSI_REMAP);
	pci_write_config_word(vmd->dev, PCI_REG_VMCONFIG, reg);
}

static int vmd_create_irq_domain(struct vmd_dev *vmd)
{
	struct fwnode_handle *fn;
@@ -325,6 +343,13 @@ static int vmd_create_irq_domain(struct vmd_dev *vmd)

static void vmd_remove_irq_domain(struct vmd_dev *vmd)
{
	/*
	 * Some production BIOS won't enable remapping between soft reboots.
	 * Ensure remapping is restored before unloading the driver.
	 */
	if (!vmd->msix_count)
		vmd_set_msi_remapping(vmd, true);

	if (vmd->irq_domain) {
		struct fwnode_handle *fn = vmd->irq_domain->fwnode;

@@ -679,15 +704,32 @@ static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features)

	sd->node = pcibus_to_node(vmd->dev->bus);

	/*
	 * Currently MSI remapping must be enabled in guest passthrough mode
	 * due to some missing interrupt remapping plumbing. This is probably
	 * acceptable because the guest is usually CPU-limited and MSI
	 * remapping doesn't become a performance bottleneck.
	 */
	if (!(features & VMD_FEAT_CAN_BYPASS_MSI_REMAP) ||
	    offset[0] || offset[1]) {
		ret = vmd_alloc_irqs(vmd);
		if (ret)
			return ret;

		vmd_set_msi_remapping(vmd, true);

		ret = vmd_create_irq_domain(vmd);
		if (ret)
			return ret;

		/*
	 * Override the irq domain bus token so the domain can be distinguished
	 * from a regular PCI/MSI domain.
		 * Override the IRQ domain bus token so the domain can be
		 * distinguished from a regular PCI/MSI domain.
		 */
		irq_domain_update_bus_token(vmd->irq_domain, DOMAIN_BUS_VMD_MSI);
	} else {
		vmd_set_msi_remapping(vmd, false);
	}

	pci_add_resource(&resources, &vmd->resources[0]);
	pci_add_resource_offset(&resources, &vmd->resources[1], offset[0]);
@@ -753,10 +795,6 @@ static int vmd_probe(struct pci_dev *dev, const struct pci_device_id *id)
	if (features & VMD_FEAT_OFFSET_FIRST_VECTOR)
		vmd->first_vec = 1;

	err = vmd_alloc_irqs(vmd);
	if (err)
		return err;

	spin_lock_init(&vmd->cfg_lock);
	pci_set_drvdata(dev, vmd);
	err = vmd_enable_domain(vmd, features);
@@ -825,7 +863,8 @@ static const struct pci_device_id vmd_ids[] = {
		.driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP,},
	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VMD_28C0),
		.driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW |
				VMD_FEAT_HAS_BUS_RESTRICTIONS,},
				VMD_FEAT_HAS_BUS_RESTRICTIONS |
				VMD_FEAT_CAN_BYPASS_MSI_REMAP,},
	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x467f),
		.driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW_VSCAP |
				VMD_FEAT_HAS_BUS_RESTRICTIONS |