Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0b4d48cb authored by Joerg Roedel's avatar Joerg Roedel
Browse files

iommu/amd: Implement MSI routines for interrupt remapping



Add routines to setup interrupt remapping for MSI
interrupts.

Signed-off-by: default avatarJoerg Roedel <joerg.roedel@amd.com>
parent 5527de74
Loading
Loading
Loading
Loading
+74 −0
Original line number Diff line number Diff line
@@ -4126,4 +4126,78 @@ static int free_irq(int irq)
	return 0;
}

static void compose_msi_msg(struct pci_dev *pdev,
			    unsigned int irq, unsigned int dest,
			    struct msi_msg *msg, u8 hpet_id)
{
	struct irq_2_iommu *irte_info;
	struct irq_cfg *cfg;
	union irte irte;

	cfg = irq_get_chip_data(irq);
	if (!cfg)
		return;

	irte_info = &cfg->irq_2_iommu;

	irte.val		= 0;
	irte.fields.vector	= cfg->vector;
	irte.fields.int_type    = apic->irq_delivery_mode;
	irte.fields.destination	= dest;
	irte.fields.dm		= apic->irq_dest_mode;
	irte.fields.valid	= 1;

	modify_irte(irte_info->sub_handle, irte_info->irte_index, irte);

	msg->address_hi = MSI_ADDR_BASE_HI;
	msg->address_lo = MSI_ADDR_BASE_LO;
	msg->data       = irte_info->irte_index;
}

static int msi_alloc_irq(struct pci_dev *pdev, int irq, int nvec)
{
	struct irq_cfg *cfg;
	int index;
	u16 devid;

	if (!pdev)
		return -EINVAL;

	cfg = irq_get_chip_data(irq);
	if (!cfg)
		return -EINVAL;

	devid = get_device_id(&pdev->dev);
	index = alloc_irq_index(cfg, devid, nvec);

	return index < 0 ? MAX_IRQS_PER_TABLE : index;
}

static int msi_setup_irq(struct pci_dev *pdev, unsigned int irq,
			 int index, int offset)
{
	struct irq_2_iommu *irte_info;
	struct irq_cfg *cfg;
	u16 devid;

	if (!pdev)
		return -EINVAL;

	cfg = irq_get_chip_data(irq);
	if (!cfg)
		return -EINVAL;

	if (index >= MAX_IRQS_PER_TABLE)
		return 0;

	devid		= get_device_id(&pdev->dev);
	irte_info	= &cfg->irq_2_iommu;

	irte_info->sub_handle = devid;
	irte_info->irte_index = index + offset;
	irte_info->iommu      = (void *)cfg;

	return 0;
}

#endif