Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 373570
b: refs/heads/master
c: bb5547a
h: refs/heads/master
v: v3
  • Loading branch information
Varun Sethi authored and Joerg Roedel committed Apr 2, 2013
1 parent 43643b4 commit a219925
Show file tree
Hide file tree
Showing 14 changed files with 103 additions and 233 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: 83ed9c13e37e352b5a16caca01798c2766d91c29
refs/heads/master: bb5547acfcd842950b8a22aa83f84af93388b9f2
14 changes: 0 additions & 14 deletions trunk/Documentation/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1226,20 +1226,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted.

iucv= [HW,NET]

ivrs_ioapic [HW,X86_64]
Provide an override to the IOAPIC-ID<->DEVICE-ID
mapping provided in the IVRS ACPI table. For
example, to map IOAPIC-ID decimal 10 to
PCI device 00:14.0 write the parameter as:
ivrs_ioapic[10]=00:14.0

ivrs_hpet [HW,X86_64]
Provide an override to the HPET-ID<->DEVICE-ID
mapping provided in the IVRS ACPI table. For
example, to map HPET-ID decimal 0 to
PCI device 00:14.0 write the parameter as:
ivrs_hpet[0]=00:14.0

js= [HW,JOY] Analog joystick
See Documentation/input/joystick.txt.

Expand Down
138 changes: 75 additions & 63 deletions trunk/drivers/iommu/amd_iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,9 @@ static void iommu_print_event(struct amd_iommu *iommu, void *__evt)
static void iommu_poll_events(struct amd_iommu *iommu)
{
u32 head, tail;
unsigned long flags;

spin_lock_irqsave(&iommu->lock, flags);

head = readl(iommu->mmio_base + MMIO_EVT_HEAD_OFFSET);
tail = readl(iommu->mmio_base + MMIO_EVT_TAIL_OFFSET);
Expand All @@ -711,6 +714,8 @@ static void iommu_poll_events(struct amd_iommu *iommu)
}

writel(head, iommu->mmio_base + MMIO_EVT_HEAD_OFFSET);

spin_unlock_irqrestore(&iommu->lock, flags);
}

static void iommu_handle_ppr_entry(struct amd_iommu *iommu, u64 *raw)
Expand All @@ -735,11 +740,17 @@ static void iommu_handle_ppr_entry(struct amd_iommu *iommu, u64 *raw)

static void iommu_poll_ppr_log(struct amd_iommu *iommu)
{
unsigned long flags;
u32 head, tail;

if (iommu->ppr_log == NULL)
return;

/* enable ppr interrupts again */
writel(MMIO_STATUS_PPR_INT_MASK, iommu->mmio_base + MMIO_STATUS_OFFSET);

spin_lock_irqsave(&iommu->lock, flags);

head = readl(iommu->mmio_base + MMIO_PPR_HEAD_OFFSET);
tail = readl(iommu->mmio_base + MMIO_PPR_TAIL_OFFSET);

Expand Down Expand Up @@ -775,50 +786,34 @@ static void iommu_poll_ppr_log(struct amd_iommu *iommu)
head = (head + PPR_ENTRY_SIZE) % PPR_LOG_SIZE;
writel(head, iommu->mmio_base + MMIO_PPR_HEAD_OFFSET);

/*
* Release iommu->lock because ppr-handling might need to
* re-acquire it
*/
spin_unlock_irqrestore(&iommu->lock, flags);

/* Handle PPR entry */
iommu_handle_ppr_entry(iommu, entry);

spin_lock_irqsave(&iommu->lock, flags);

/* Refresh ring-buffer information */
head = readl(iommu->mmio_base + MMIO_PPR_HEAD_OFFSET);
tail = readl(iommu->mmio_base + MMIO_PPR_TAIL_OFFSET);
}

spin_unlock_irqrestore(&iommu->lock, flags);
}

irqreturn_t amd_iommu_int_thread(int irq, void *data)
{
struct amd_iommu *iommu = (struct amd_iommu *) data;
u32 status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET);

while (status & (MMIO_STATUS_EVT_INT_MASK | MMIO_STATUS_PPR_INT_MASK)) {
/* Enable EVT and PPR interrupts again */
writel((MMIO_STATUS_EVT_INT_MASK | MMIO_STATUS_PPR_INT_MASK),
iommu->mmio_base + MMIO_STATUS_OFFSET);

if (status & MMIO_STATUS_EVT_INT_MASK) {
pr_devel("AMD-Vi: Processing IOMMU Event Log\n");
iommu_poll_events(iommu);
}

if (status & MMIO_STATUS_PPR_INT_MASK) {
pr_devel("AMD-Vi: Processing IOMMU PPR Log\n");
iommu_poll_ppr_log(iommu);
}
struct amd_iommu *iommu;

/*
* Hardware bug: ERBT1312
* When re-enabling interrupt (by writing 1
* to clear the bit), the hardware might also try to set
* the interrupt bit in the event status register.
* In this scenario, the bit will be set, and disable
* subsequent interrupts.
*
* Workaround: The IOMMU driver should read back the
* status register and check if the interrupt bits are cleared.
* If not, driver will need to go through the interrupt handler
* again and re-clear the bits
*/
status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET);
for_each_iommu(iommu) {
iommu_poll_events(iommu);
iommu_poll_ppr_log(iommu);
}

return IRQ_HANDLED;
}

Expand Down Expand Up @@ -2843,6 +2838,24 @@ static void unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
spin_unlock_irqrestore(&domain->lock, flags);
}

/*
* This is a special map_sg function which is used if we should map a
* device which is not handled by an AMD IOMMU in the system.
*/
static int map_sg_no_iommu(struct device *dev, struct scatterlist *sglist,
int nelems, int dir)
{
struct scatterlist *s;
int i;

for_each_sg(sglist, s, nelems, i) {
s->dma_address = (dma_addr_t)sg_phys(s);
s->dma_length = s->length;
}

return nelems;
}

/*
* The exported map_sg function for dma_ops (handles scatter-gather
* lists).
Expand All @@ -2862,7 +2875,9 @@ static int map_sg(struct device *dev, struct scatterlist *sglist,
INC_STATS_COUNTER(cnt_map_sg);

domain = get_domain(dev);
if (IS_ERR(domain))
if (PTR_ERR(domain) == -EINVAL)
return map_sg_no_iommu(dev, sglist, nelems, dir);
else if (IS_ERR(domain))
return 0;

dma_mask = *dev->dma_mask;
Expand Down Expand Up @@ -3395,7 +3410,7 @@ static size_t amd_iommu_unmap(struct iommu_domain *dom, unsigned long iova,
}

static phys_addr_t amd_iommu_iova_to_phys(struct iommu_domain *dom,
unsigned long iova)
dma_addr_t iova)
{
struct protection_domain *domain = dom->priv;
unsigned long offset_mask;
Expand Down Expand Up @@ -3932,9 +3947,6 @@ static struct irq_remap_table *get_irq_table(u16 devid, bool ioapic)
if (!table)
goto out;

/* Initialize table spin-lock */
spin_lock_init(&table->lock);

if (ioapic)
/* Keep the first 32 indexes free for IOAPIC interrupts */
table->min_index = 32;
Expand Down Expand Up @@ -3995,17 +4007,17 @@ static int alloc_irq_index(struct irq_cfg *cfg, u16 devid, int count)
c = 0;

if (c == count) {
struct irq_2_irte *irte_info;
struct irq_2_iommu *irte_info;

for (; c != 0; --c)
table->table[index - c + 1] = IRTE_ALLOCATED;

index -= count - 1;

cfg->remapped = 1;
irte_info = &cfg->irq_2_irte;
irte_info->devid = devid;
irte_info->index = index;
irte_info = &cfg->irq_2_iommu;
irte_info->sub_handle = devid;
irte_info->irte_index = index;

goto out;
}
Expand Down Expand Up @@ -4086,7 +4098,7 @@ static int setup_ioapic_entry(int irq, struct IO_APIC_route_entry *entry,
struct io_apic_irq_attr *attr)
{
struct irq_remap_table *table;
struct irq_2_irte *irte_info;
struct irq_2_iommu *irte_info;
struct irq_cfg *cfg;
union irte irte;
int ioapic_id;
Expand All @@ -4098,7 +4110,7 @@ static int setup_ioapic_entry(int irq, struct IO_APIC_route_entry *entry,
if (!cfg)
return -EINVAL;

irte_info = &cfg->irq_2_irte;
irte_info = &cfg->irq_2_iommu;
ioapic_id = mpc_ioapic_id(attr->ioapic);
devid = get_ioapic_devid(ioapic_id);

Expand All @@ -4113,8 +4125,8 @@ static int setup_ioapic_entry(int irq, struct IO_APIC_route_entry *entry,

/* Setup IRQ remapping info */
cfg->remapped = 1;
irte_info->devid = devid;
irte_info->index = index;
irte_info->sub_handle = devid;
irte_info->irte_index = index;

/* Setup IRTE for IOMMU */
irte.val = 0;
Expand Down Expand Up @@ -4148,7 +4160,7 @@ static int setup_ioapic_entry(int irq, struct IO_APIC_route_entry *entry,
static int set_affinity(struct irq_data *data, const struct cpumask *mask,
bool force)
{
struct irq_2_irte *irte_info;
struct irq_2_iommu *irte_info;
unsigned int dest, irq;
struct irq_cfg *cfg;
union irte irte;
Expand All @@ -4159,12 +4171,12 @@ static int set_affinity(struct irq_data *data, const struct cpumask *mask,

cfg = data->chip_data;
irq = data->irq;
irte_info = &cfg->irq_2_irte;
irte_info = &cfg->irq_2_iommu;

if (!cpumask_intersects(mask, cpu_online_mask))
return -EINVAL;

if (get_irte(irte_info->devid, irte_info->index, &irte))
if (get_irte(irte_info->sub_handle, irte_info->irte_index, &irte))
return -EBUSY;

if (assign_irq_vector(irq, cfg, mask))
Expand All @@ -4180,7 +4192,7 @@ static int set_affinity(struct irq_data *data, const struct cpumask *mask,
irte.fields.vector = cfg->vector;
irte.fields.destination = dest;

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

if (cfg->move_in_progress)
send_cleanup_vector(cfg);
Expand All @@ -4192,16 +4204,16 @@ static int set_affinity(struct irq_data *data, const struct cpumask *mask,

static int free_irq(int irq)
{
struct irq_2_irte *irte_info;
struct irq_2_iommu *irte_info;
struct irq_cfg *cfg;

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

irte_info = &cfg->irq_2_irte;
irte_info = &cfg->irq_2_iommu;

free_irte(irte_info->devid, irte_info->index);
free_irte(irte_info->sub_handle, irte_info->irte_index);

return 0;
}
Expand All @@ -4210,15 +4222,15 @@ 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_irte *irte_info;
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_irte;
irte_info = &cfg->irq_2_iommu;

irte.val = 0;
irte.fields.vector = cfg->vector;
Expand All @@ -4227,11 +4239,11 @@ static void compose_msi_msg(struct pci_dev *pdev,
irte.fields.dm = apic->irq_dest_mode;
irte.fields.valid = 1;

modify_irte(irte_info->devid, irte_info->index, irte);
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->index;
msg->data = irte_info->irte_index;
}

static int msi_alloc_irq(struct pci_dev *pdev, int irq, int nvec)
Expand All @@ -4256,7 +4268,7 @@ static int msi_alloc_irq(struct pci_dev *pdev, int irq, int nvec)
static int msi_setup_irq(struct pci_dev *pdev, unsigned int irq,
int index, int offset)
{
struct irq_2_irte *irte_info;
struct irq_2_iommu *irte_info;
struct irq_cfg *cfg;
u16 devid;

Expand All @@ -4271,26 +4283,26 @@ static int msi_setup_irq(struct pci_dev *pdev, unsigned int irq,
return 0;

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

cfg->remapped = 1;
irte_info->devid = devid;
irte_info->index = index + offset;
irte_info->sub_handle = devid;
irte_info->irte_index = index + offset;

return 0;
}

static int setup_hpet_msi(unsigned int irq, unsigned int id)
{
struct irq_2_irte *irte_info;
struct irq_2_iommu *irte_info;
struct irq_cfg *cfg;
int index, devid;

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

irte_info = &cfg->irq_2_irte;
irte_info = &cfg->irq_2_iommu;
devid = get_hpet_devid(id);
if (devid < 0)
return devid;
Expand All @@ -4300,8 +4312,8 @@ static int setup_hpet_msi(unsigned int irq, unsigned int id)
return index;

cfg->remapped = 1;
irte_info->devid = devid;
irte_info->index = index;
irte_info->sub_handle = devid;
irte_info->irte_index = index;

return 0;
}
Expand Down
Loading

0 comments on commit a219925

Please sign in to comment.