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
This commit is contained in:
commit
04dcc048f3
@ -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);
|
||||
|
@ -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 = 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);
|
||||
|
||||
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.
|
||||
* 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.
|
||||
*/
|
||||
irq_domain_update_bus_token(vmd->irq_domain, DOMAIN_BUS_VMD_MSI);
|
||||
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.
|
||||
*/
|
||||
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 |
|
||||
|
Loading…
Reference in New Issue
Block a user