Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 302720
b: refs/heads/master
c: 5e2b930
h: refs/heads/master
v: v3
  • Loading branch information
Joerg Roedel committed May 7, 2012
1 parent 04fb773 commit 91c243f
Show file tree
Hide file tree
Showing 7 changed files with 203 additions and 115 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: 9d619f65722236e0e0c35467d1528caed206e439
refs/heads/master: 5e2b930b0784a30c98dee8e9d79c1f84c31f7209
26 changes: 26 additions & 0 deletions trunk/arch/x86/include/asm/intr_remapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

struct IO_APIC_route_entry;
struct io_apic_irq_attr;
struct pci_dev;

extern int intr_remapping_enabled;

Expand All @@ -44,6 +45,13 @@ extern int intr_set_affinity(struct irq_data *data,
const struct cpumask *mask,
bool force);
extern void intr_free_irq(int irq);
extern void intr_compose_msi_msg(struct pci_dev *pdev,
unsigned int irq, unsigned int dest,
struct msi_msg *msg, u8 hpet_id);
extern int intr_msi_alloc_irq(struct pci_dev *pdev, int irq, int nvec);
extern int intr_msi_setup_irq(struct pci_dev *pdev, unsigned int irq,
int index, int sub_handle);
extern int intr_setup_hpet_msi(unsigned int irq, unsigned int id);

#else /* CONFIG_IRQ_REMAP */

Expand All @@ -70,6 +78,24 @@ static inline int intr_set_affinity(struct irq_data *data,
return 0;
}
static inline void intr_free_irq(int irq) { }
static inline void intr_compose_msi_msg(struct pci_dev *pdev,
unsigned int irq, unsigned int dest,
struct msi_msg *msg, u8 hpet_id)
{
}
static inline int intr_msi_alloc_irq(struct pci_dev *pdev, int irq, int nvec)
{
return -ENODEV;
}
static inline int intr_msi_setup_irq(struct pci_dev *pdev, unsigned int irq,
int index, int sub_handle)
{
return -ENODEV;
}
static inline int intr_setup_hpet_msi(unsigned int irq, unsigned int id)
{
return -ENODEV;
}
#endif /* CONFIG_IRQ_REMAP */

#endif /* __X86_INTR_REMAPPING_H */
23 changes: 0 additions & 23 deletions trunk/arch/x86/include/asm/irq_remapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,11 @@

#ifdef CONFIG_IRQ_REMAP
static void irq_remap_modify_chip_defaults(struct irq_chip *chip);
static inline void prepare_irte(struct irte *irte, int vector,
unsigned int dest)
{
memset(irte, 0, sizeof(*irte));

irte->present = 1;
irte->dst_mode = apic->irq_dest_mode;
/*
* Trigger mode in the IRTE will always be edge, and for IO-APIC, the
* actual level or edge trigger will be setup in the IO-APIC
* RTE. This will help simplify level triggered irq migration.
* For more details, see the comments (in io_apic.c) explainig IO-APIC
* irq migration in the presence of interrupt-remapping.
*/
irte->trigger_mode = 0;
irte->dlvry_mode = apic->irq_delivery_mode;
irte->vector = vector;
irte->dest_id = IRTE_DEST(dest);
irte->redir_hint = 1;
}
static inline bool irq_remapped(struct irq_cfg *cfg)
{
return cfg->irq_2_iommu.iommu != NULL;
}
#else
static void prepare_irte(struct irte *irte, int vector, unsigned int dest)
{
}
static inline bool irq_remapped(struct irq_cfg *cfg)
{
return false;
Expand Down
119 changes: 28 additions & 91 deletions trunk/arch/x86/kernel/apic/io_apic.c
Original file line number Diff line number Diff line change
Expand Up @@ -3070,54 +3070,34 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq,
dest = apic->cpu_mask_to_apicid_and(cfg->domain, apic->target_cpus());

if (irq_remapped(cfg)) {
struct irte irte;
int ir_index;
u16 sub_handle;

ir_index = map_irq_to_irte_handle(irq, &sub_handle);
BUG_ON(ir_index == -1);

prepare_irte(&irte, cfg->vector, dest);

/* Set source-id of interrupt request */
if (pdev)
set_msi_sid(&irte, pdev);
else
set_hpet_sid(&irte, hpet_id);

modify_irte(irq, &irte);
intr_compose_msi_msg(pdev, irq, dest, msg, hpet_id);
return err;
}

if (x2apic_enabled())
msg->address_hi = MSI_ADDR_BASE_HI |
MSI_ADDR_EXT_DEST_ID(dest);
else
msg->address_hi = MSI_ADDR_BASE_HI;
msg->data = sub_handle;
msg->address_lo = MSI_ADDR_BASE_LO | MSI_ADDR_IR_EXT_INT |
MSI_ADDR_IR_SHV |
MSI_ADDR_IR_INDEX1(ir_index) |
MSI_ADDR_IR_INDEX2(ir_index);
} else {
if (x2apic_enabled())
msg->address_hi = MSI_ADDR_BASE_HI |
MSI_ADDR_EXT_DEST_ID(dest);
else
msg->address_hi = MSI_ADDR_BASE_HI;

msg->address_lo =
MSI_ADDR_BASE_LO |
((apic->irq_dest_mode == 0) ?
MSI_ADDR_DEST_MODE_PHYSICAL:
MSI_ADDR_DEST_MODE_LOGICAL) |
((apic->irq_delivery_mode != dest_LowestPrio) ?
MSI_ADDR_REDIRECTION_CPU:
MSI_ADDR_REDIRECTION_LOWPRI) |
MSI_ADDR_DEST_ID(dest);
msg->address_lo =
MSI_ADDR_BASE_LO |
((apic->irq_dest_mode == 0) ?
MSI_ADDR_DEST_MODE_PHYSICAL:
MSI_ADDR_DEST_MODE_LOGICAL) |
((apic->irq_delivery_mode != dest_LowestPrio) ?
MSI_ADDR_REDIRECTION_CPU:
MSI_ADDR_REDIRECTION_LOWPRI) |
MSI_ADDR_DEST_ID(dest);

msg->data =
MSI_DATA_TRIGGER_EDGE |
MSI_DATA_LEVEL_ASSERT |
((apic->irq_delivery_mode != dest_LowestPrio) ?
MSI_DATA_DELIVERY_FIXED:
MSI_DATA_DELIVERY_LOWPRI) |
MSI_DATA_VECTOR(cfg->vector);

msg->data =
MSI_DATA_TRIGGER_EDGE |
MSI_DATA_LEVEL_ASSERT |
((apic->irq_delivery_mode != dest_LowestPrio) ?
MSI_DATA_DELIVERY_FIXED:
MSI_DATA_DELIVERY_LOWPRI) |
MSI_DATA_VECTOR(cfg->vector);
}
return err;
}

Expand Down Expand Up @@ -3160,33 +3140,6 @@ static struct irq_chip msi_chip = {
.irq_retrigger = ioapic_retrigger_irq,
};

/*
* Map the PCI dev to the corresponding remapping hardware unit
* and allocate 'nvec' consecutive interrupt-remapping table entries
* in it.
*/
static int msi_alloc_irte(struct pci_dev *dev, int irq, int nvec)
{
struct intel_iommu *iommu;
int index;

iommu = map_dev_to_ir(dev);
if (!iommu) {
printk(KERN_ERR
"Unable to map PCI %s to iommu\n", pci_name(dev));
return -ENOENT;
}

index = alloc_irte(iommu, irq, nvec);
if (index < 0) {
printk(KERN_ERR
"Unable to allocate %d IRTE for PCI %s\n", nvec,
pci_name(dev));
return -ENOSPC;
}
return index;
}

static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int irq)
{
struct irq_chip *chip = &msi_chip;
Expand Down Expand Up @@ -3217,7 +3170,6 @@ int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
int node, ret, sub_handle, index = 0;
unsigned int irq, irq_want;
struct msi_desc *msidesc;
struct intel_iommu *iommu = NULL;

/* x86 doesn't support multiple MSI yet */
if (type == PCI_CAP_ID_MSI && nvec > 1)
Expand All @@ -3239,23 +3191,15 @@ int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
* allocate the consecutive block of IRTE's
* for 'nvec'
*/
index = msi_alloc_irte(dev, irq, nvec);
index = intr_msi_alloc_irq(dev, irq, nvec);
if (index < 0) {
ret = index;
goto error;
}
} else {
iommu = map_dev_to_ir(dev);
if (!iommu) {
ret = -ENOENT;
ret = intr_msi_setup_irq(dev, irq, index, sub_handle);
if (ret < 0)
goto error;
}
/*
* setup the mapping between the irq and the IRTE
* base index, the sub_handle pointing to the
* appropriate interrupt remap table entry.
*/
set_irte_irq(irq, iommu, index, sub_handle);
}
no_ir:
ret = setup_msi_irq(dev, msidesc, irq);
Expand Down Expand Up @@ -3374,14 +3318,7 @@ int arch_setup_hpet_msi(unsigned int irq, unsigned int id)
int ret;

if (intr_remapping_enabled) {
struct intel_iommu *iommu = map_hpet_to_ir(id);
int index;

if (!iommu)
return -1;

index = alloc_irte(iommu, irq, 1);
if (index < 0)
if (!intr_setup_hpet_msi(irq, id))
return -1;
}

Expand Down
97 changes: 97 additions & 0 deletions trunk/drivers/iommu/intel_intr_remapping.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <acpi/acpi.h>
#include <asm/intr_remapping.h>
#include <asm/pci-direct.h>
#include <asm/msidef.h>

#include "intr_remapping.h"

Expand Down Expand Up @@ -955,6 +956,98 @@ intel_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
return 0;
}

static void intel_compose_msi_msg(struct pci_dev *pdev,
unsigned int irq, unsigned int dest,
struct msi_msg *msg, u8 hpet_id)
{
struct irq_cfg *cfg;
struct irte irte;
u16 sub_handle;
int ir_index;

cfg = irq_get_chip_data(irq);

ir_index = map_irq_to_irte_handle(irq, &sub_handle);
BUG_ON(ir_index == -1);

prepare_irte(&irte, cfg->vector, dest);

/* Set source-id of interrupt request */
if (pdev)
set_msi_sid(&irte, pdev);
else
set_hpet_sid(&irte, hpet_id);

modify_irte(irq, &irte);

msg->address_hi = MSI_ADDR_BASE_HI;
msg->data = sub_handle;
msg->address_lo = MSI_ADDR_BASE_LO | MSI_ADDR_IR_EXT_INT |
MSI_ADDR_IR_SHV |
MSI_ADDR_IR_INDEX1(ir_index) |
MSI_ADDR_IR_INDEX2(ir_index);
}

/*
* Map the PCI dev to the corresponding remapping hardware unit
* and allocate 'nvec' consecutive interrupt-remapping table entries
* in it.
*/
static int intel_msi_alloc_irq(struct pci_dev *dev, int irq, int nvec)
{
struct intel_iommu *iommu;
int index;

iommu = map_dev_to_ir(dev);
if (!iommu) {
printk(KERN_ERR
"Unable to map PCI %s to iommu\n", pci_name(dev));
return -ENOENT;
}

index = alloc_irte(iommu, irq, nvec);
if (index < 0) {
printk(KERN_ERR
"Unable to allocate %d IRTE for PCI %s\n", nvec,
pci_name(dev));
return -ENOSPC;
}
return index;
}

static int intel_msi_setup_irq(struct pci_dev *pdev, unsigned int irq,
int index, int sub_handle)
{
struct intel_iommu *iommu;

iommu = map_dev_to_ir(pdev);
if (!iommu)
return -ENOENT;
/*
* setup the mapping between the irq and the IRTE
* base index, the sub_handle pointing to the
* appropriate interrupt remap table entry.
*/
set_irte_irq(irq, iommu, index, sub_handle);

return 0;
}

static int intel_setup_hpet_msi(unsigned int irq, unsigned int id)
{
struct intel_iommu *iommu = map_hpet_to_ir(id);
int index;

if (!iommu)
return -1;

index = alloc_irte(iommu, irq, 1);
if (index < 0)
return -1;

return 0;
}

struct irq_remap_ops intel_irq_remap_ops = {
.supported = intel_intr_remapping_supported,
.hardware_init = dmar_table_init,
Expand All @@ -965,4 +1058,8 @@ struct irq_remap_ops intel_irq_remap_ops = {
.setup_ioapic_entry = intel_setup_ioapic_entry,
.set_affinity = intel_ioapic_set_affinity,
.free_irq = free_irte,
.compose_msi_msg = intel_compose_msi_msg,
.msi_alloc_irq = intel_msi_alloc_irq,
.msi_setup_irq = intel_msi_setup_irq,
.setup_hpet_msi = intel_setup_hpet_msi,
};
Loading

0 comments on commit 91c243f

Please sign in to comment.