mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 11:11:45 -04:00
Merge branch 'genirq-v28-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
This merges branches irq/genirq, irq/sparseirq-v4, timers/hpet-percpu and x86/uv. The sparseirq branch is just preliminary groundwork: no sparse IRQs are actually implemented by this tree anymore - just the new APIs are added while keeping the old way intact as well (the new APIs map 1:1 to irq_desc[]). The 'real' sparse IRQ support will then be a relatively small patch ontop of this - with a v2.6.29 merge target. * 'genirq-v28-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (178 commits) genirq: improve include files intr_remapping: fix typo io_apic: make irq_mis_count available on 64-bit too genirq: fix name space collisions of nr_irqs in arch/* genirq: fix name space collision of nr_irqs in autoprobe.c genirq: use iterators for irq_desc loops proc: fixup irq iterator genirq: add reverse iterator for irq_desc x86: move ack_bad_irq() to irq.c x86: unify show_interrupts() and proc helpers x86: cleanup show_interrupts genirq: cleanup the sparseirq modifications genirq: remove artifacts from sparseirq removal genirq: revert dynarray genirq: remove irq_to_desc_alloc genirq: remove sparse irq code genirq: use inline function for irq_to_desc genirq: consolidate nr_irqs and for_each_irq_desc() x86: remove sparse irq from Kconfig genirq: define nr_irqs for architectures with GENERIC_HARDIRQS=n ...
This commit is contained in:
commit
9301975ec2
111 changed files with 3716 additions and 6226 deletions
|
|
@ -193,7 +193,7 @@ dmar_parse_dev(struct dmar_drhd_unit *dmaru)
|
|||
{
|
||||
struct acpi_dmar_hardware_unit *drhd;
|
||||
static int include_all;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
drhd = (struct acpi_dmar_hardware_unit *) dmaru->hdr;
|
||||
|
||||
|
|
@ -212,7 +212,7 @@ dmar_parse_dev(struct dmar_drhd_unit *dmaru)
|
|||
include_all = 1;
|
||||
}
|
||||
|
||||
if (ret || (dmaru->devices_cnt == 0 && !dmaru->include_all)) {
|
||||
if (ret) {
|
||||
list_del(&dmaru->list);
|
||||
kfree(dmaru);
|
||||
}
|
||||
|
|
@ -289,6 +289,24 @@ dmar_table_print_dmar_entry(struct acpi_dmar_header *header)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* dmar_table_detect - checks to see if the platform supports DMAR devices
|
||||
*/
|
||||
static int __init dmar_table_detect(void)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
|
||||
/* if we could find DMAR table, then there are DMAR devices */
|
||||
status = acpi_get_table(ACPI_SIG_DMAR, 0,
|
||||
(struct acpi_table_header **)&dmar_tbl);
|
||||
|
||||
if (ACPI_SUCCESS(status) && !dmar_tbl) {
|
||||
printk (KERN_WARNING PREFIX "Unable to map DMAR\n");
|
||||
status = AE_NOT_FOUND;
|
||||
}
|
||||
|
||||
return (ACPI_SUCCESS(status) ? 1 : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* parse_dmar_table - parses the DMA reporting table
|
||||
|
|
@ -300,6 +318,12 @@ parse_dmar_table(void)
|
|||
struct acpi_dmar_header *entry_header;
|
||||
int ret = 0;
|
||||
|
||||
/*
|
||||
* Do it again, earlier dmar_tbl mapping could be mapped with
|
||||
* fixed map.
|
||||
*/
|
||||
dmar_table_detect();
|
||||
|
||||
dmar = (struct acpi_table_dmar *)dmar_tbl;
|
||||
if (!dmar)
|
||||
return -ENODEV;
|
||||
|
|
@ -373,10 +397,10 @@ dmar_find_matched_drhd_unit(struct pci_dev *dev)
|
|||
|
||||
int __init dmar_dev_scope_init(void)
|
||||
{
|
||||
struct dmar_drhd_unit *drhd;
|
||||
struct dmar_drhd_unit *drhd, *drhd_n;
|
||||
int ret = -ENODEV;
|
||||
|
||||
for_each_drhd_unit(drhd) {
|
||||
list_for_each_entry_safe(drhd, drhd_n, &dmar_drhd_units, list) {
|
||||
ret = dmar_parse_dev(drhd);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
@ -384,8 +408,8 @@ int __init dmar_dev_scope_init(void)
|
|||
|
||||
#ifdef CONFIG_DMAR
|
||||
{
|
||||
struct dmar_rmrr_unit *rmrr;
|
||||
for_each_rmrr_units(rmrr) {
|
||||
struct dmar_rmrr_unit *rmrr, *rmrr_n;
|
||||
list_for_each_entry_safe(rmrr, rmrr_n, &dmar_rmrr_units, list) {
|
||||
ret = rmrr_parse_dev(rmrr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
|
@ -430,30 +454,11 @@ int __init dmar_table_init(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* early_dmar_detect - checks to see if the platform supports DMAR devices
|
||||
*/
|
||||
int __init early_dmar_detect(void)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
|
||||
/* if we could find DMAR table, then there are DMAR devices */
|
||||
status = acpi_get_table(ACPI_SIG_DMAR, 0,
|
||||
(struct acpi_table_header **)&dmar_tbl);
|
||||
|
||||
if (ACPI_SUCCESS(status) && !dmar_tbl) {
|
||||
printk (KERN_WARNING PREFIX "Unable to map DMAR\n");
|
||||
status = AE_NOT_FOUND;
|
||||
}
|
||||
|
||||
return (ACPI_SUCCESS(status) ? 1 : 0);
|
||||
}
|
||||
|
||||
void __init detect_intel_iommu(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = early_dmar_detect();
|
||||
ret = dmar_table_detect();
|
||||
|
||||
#ifdef CONFIG_DMAR
|
||||
{
|
||||
|
|
@ -479,14 +484,16 @@ void __init detect_intel_iommu(void)
|
|||
" x2apic support\n");
|
||||
|
||||
dmar_disabled = 1;
|
||||
return;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (ret && !no_iommu && !iommu_detected && !swiotlb &&
|
||||
!dmar_disabled)
|
||||
iommu_detected = 1;
|
||||
}
|
||||
end:
|
||||
#endif
|
||||
dmar_tbl = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -126,7 +126,8 @@ int __ht_create_irq(struct pci_dev *dev, int idx, ht_irq_update_t *update)
|
|||
cfg->msg.address_hi = 0xffffffff;
|
||||
|
||||
irq = create_irq();
|
||||
if (irq < 0) {
|
||||
|
||||
if (irq <= 0) {
|
||||
kfree(cfg);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/dmar.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/jiffies.h>
|
||||
|
|
@ -11,41 +12,64 @@ static struct ioapic_scope ir_ioapic[MAX_IO_APICS];
|
|||
static int ir_ioapic_num;
|
||||
int intr_remapping_enabled;
|
||||
|
||||
static struct {
|
||||
struct irq_2_iommu {
|
||||
struct intel_iommu *iommu;
|
||||
u16 irte_index;
|
||||
u16 sub_handle;
|
||||
u8 irte_mask;
|
||||
} irq_2_iommu[NR_IRQS];
|
||||
};
|
||||
|
||||
static struct irq_2_iommu irq_2_iommuX[NR_IRQS];
|
||||
|
||||
static struct irq_2_iommu *irq_2_iommu(unsigned int irq)
|
||||
{
|
||||
return (irq < nr_irqs) ? irq_2_iommuX + irq : NULL;
|
||||
}
|
||||
|
||||
static struct irq_2_iommu *irq_2_iommu_alloc(unsigned int irq)
|
||||
{
|
||||
return irq_2_iommu(irq);
|
||||
}
|
||||
|
||||
static DEFINE_SPINLOCK(irq_2_ir_lock);
|
||||
|
||||
static struct irq_2_iommu *valid_irq_2_iommu(unsigned int irq)
|
||||
{
|
||||
struct irq_2_iommu *irq_iommu;
|
||||
|
||||
irq_iommu = irq_2_iommu(irq);
|
||||
|
||||
if (!irq_iommu)
|
||||
return NULL;
|
||||
|
||||
if (!irq_iommu->iommu)
|
||||
return NULL;
|
||||
|
||||
return irq_iommu;
|
||||
}
|
||||
|
||||
int irq_remapped(int irq)
|
||||
{
|
||||
if (irq > NR_IRQS)
|
||||
return 0;
|
||||
|
||||
if (!irq_2_iommu[irq].iommu)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
return valid_irq_2_iommu(irq) != NULL;
|
||||
}
|
||||
|
||||
int get_irte(int irq, struct irte *entry)
|
||||
{
|
||||
int index;
|
||||
struct irq_2_iommu *irq_iommu;
|
||||
|
||||
if (!entry || irq > NR_IRQS)
|
||||
if (!entry)
|
||||
return -1;
|
||||
|
||||
spin_lock(&irq_2_ir_lock);
|
||||
if (!irq_2_iommu[irq].iommu) {
|
||||
irq_iommu = valid_irq_2_iommu(irq);
|
||||
if (!irq_iommu) {
|
||||
spin_unlock(&irq_2_ir_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
index = irq_2_iommu[irq].irte_index + irq_2_iommu[irq].sub_handle;
|
||||
*entry = *(irq_2_iommu[irq].iommu->ir_table->base + index);
|
||||
index = irq_iommu->irte_index + irq_iommu->sub_handle;
|
||||
*entry = *(irq_iommu->iommu->ir_table->base + index);
|
||||
|
||||
spin_unlock(&irq_2_ir_lock);
|
||||
return 0;
|
||||
|
|
@ -54,6 +78,7 @@ int get_irte(int irq, struct irte *entry)
|
|||
int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
|
||||
{
|
||||
struct ir_table *table = iommu->ir_table;
|
||||
struct irq_2_iommu *irq_iommu;
|
||||
u16 index, start_index;
|
||||
unsigned int mask = 0;
|
||||
int i;
|
||||
|
|
@ -61,6 +86,10 @@ int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
|
|||
if (!count)
|
||||
return -1;
|
||||
|
||||
/* protect irq_2_iommu_alloc later */
|
||||
if (irq >= nr_irqs)
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* start the IRTE search from index 0.
|
||||
*/
|
||||
|
|
@ -100,10 +129,11 @@ int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
|
|||
for (i = index; i < index + count; i++)
|
||||
table->base[i].present = 1;
|
||||
|
||||
irq_2_iommu[irq].iommu = iommu;
|
||||
irq_2_iommu[irq].irte_index = index;
|
||||
irq_2_iommu[irq].sub_handle = 0;
|
||||
irq_2_iommu[irq].irte_mask = mask;
|
||||
irq_iommu = irq_2_iommu_alloc(irq);
|
||||
irq_iommu->iommu = iommu;
|
||||
irq_iommu->irte_index = index;
|
||||
irq_iommu->sub_handle = 0;
|
||||
irq_iommu->irte_mask = mask;
|
||||
|
||||
spin_unlock(&irq_2_ir_lock);
|
||||
|
||||
|
|
@ -124,31 +154,33 @@ static void qi_flush_iec(struct intel_iommu *iommu, int index, int mask)
|
|||
int map_irq_to_irte_handle(int irq, u16 *sub_handle)
|
||||
{
|
||||
int index;
|
||||
struct irq_2_iommu *irq_iommu;
|
||||
|
||||
spin_lock(&irq_2_ir_lock);
|
||||
if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) {
|
||||
irq_iommu = valid_irq_2_iommu(irq);
|
||||
if (!irq_iommu) {
|
||||
spin_unlock(&irq_2_ir_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*sub_handle = irq_2_iommu[irq].sub_handle;
|
||||
index = irq_2_iommu[irq].irte_index;
|
||||
*sub_handle = irq_iommu->sub_handle;
|
||||
index = irq_iommu->irte_index;
|
||||
spin_unlock(&irq_2_ir_lock);
|
||||
return index;
|
||||
}
|
||||
|
||||
int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle)
|
||||
{
|
||||
spin_lock(&irq_2_ir_lock);
|
||||
if (irq >= NR_IRQS || irq_2_iommu[irq].iommu) {
|
||||
spin_unlock(&irq_2_ir_lock);
|
||||
return -1;
|
||||
}
|
||||
struct irq_2_iommu *irq_iommu;
|
||||
|
||||
irq_2_iommu[irq].iommu = iommu;
|
||||
irq_2_iommu[irq].irte_index = index;
|
||||
irq_2_iommu[irq].sub_handle = subhandle;
|
||||
irq_2_iommu[irq].irte_mask = 0;
|
||||
spin_lock(&irq_2_ir_lock);
|
||||
|
||||
irq_iommu = irq_2_iommu_alloc(irq);
|
||||
|
||||
irq_iommu->iommu = iommu;
|
||||
irq_iommu->irte_index = index;
|
||||
irq_iommu->sub_handle = subhandle;
|
||||
irq_iommu->irte_mask = 0;
|
||||
|
||||
spin_unlock(&irq_2_ir_lock);
|
||||
|
||||
|
|
@ -157,16 +189,19 @@ int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle)
|
|||
|
||||
int clear_irte_irq(int irq, struct intel_iommu *iommu, u16 index)
|
||||
{
|
||||
struct irq_2_iommu *irq_iommu;
|
||||
|
||||
spin_lock(&irq_2_ir_lock);
|
||||
if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) {
|
||||
irq_iommu = valid_irq_2_iommu(irq);
|
||||
if (!irq_iommu) {
|
||||
spin_unlock(&irq_2_ir_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
irq_2_iommu[irq].iommu = NULL;
|
||||
irq_2_iommu[irq].irte_index = 0;
|
||||
irq_2_iommu[irq].sub_handle = 0;
|
||||
irq_2_iommu[irq].irte_mask = 0;
|
||||
irq_iommu->iommu = NULL;
|
||||
irq_iommu->irte_index = 0;
|
||||
irq_iommu->sub_handle = 0;
|
||||
irq_2_iommu(irq)->irte_mask = 0;
|
||||
|
||||
spin_unlock(&irq_2_ir_lock);
|
||||
|
||||
|
|
@ -178,16 +213,18 @@ int modify_irte(int irq, struct irte *irte_modified)
|
|||
int index;
|
||||
struct irte *irte;
|
||||
struct intel_iommu *iommu;
|
||||
struct irq_2_iommu *irq_iommu;
|
||||
|
||||
spin_lock(&irq_2_ir_lock);
|
||||
if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) {
|
||||
irq_iommu = valid_irq_2_iommu(irq);
|
||||
if (!irq_iommu) {
|
||||
spin_unlock(&irq_2_ir_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
iommu = irq_2_iommu[irq].iommu;
|
||||
iommu = irq_iommu->iommu;
|
||||
|
||||
index = irq_2_iommu[irq].irte_index + irq_2_iommu[irq].sub_handle;
|
||||
index = irq_iommu->irte_index + irq_iommu->sub_handle;
|
||||
irte = &iommu->ir_table->base[index];
|
||||
|
||||
set_64bit((unsigned long *)irte, irte_modified->low | (1 << 1));
|
||||
|
|
@ -203,18 +240,20 @@ int flush_irte(int irq)
|
|||
{
|
||||
int index;
|
||||
struct intel_iommu *iommu;
|
||||
struct irq_2_iommu *irq_iommu;
|
||||
|
||||
spin_lock(&irq_2_ir_lock);
|
||||
if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) {
|
||||
irq_iommu = valid_irq_2_iommu(irq);
|
||||
if (!irq_iommu) {
|
||||
spin_unlock(&irq_2_ir_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
iommu = irq_2_iommu[irq].iommu;
|
||||
iommu = irq_iommu->iommu;
|
||||
|
||||
index = irq_2_iommu[irq].irte_index + irq_2_iommu[irq].sub_handle;
|
||||
index = irq_iommu->irte_index + irq_iommu->sub_handle;
|
||||
|
||||
qi_flush_iec(iommu, index, irq_2_iommu[irq].irte_mask);
|
||||
qi_flush_iec(iommu, index, irq_iommu->irte_mask);
|
||||
spin_unlock(&irq_2_ir_lock);
|
||||
|
||||
return 0;
|
||||
|
|
@ -246,28 +285,30 @@ int free_irte(int irq)
|
|||
int index, i;
|
||||
struct irte *irte;
|
||||
struct intel_iommu *iommu;
|
||||
struct irq_2_iommu *irq_iommu;
|
||||
|
||||
spin_lock(&irq_2_ir_lock);
|
||||
if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) {
|
||||
irq_iommu = valid_irq_2_iommu(irq);
|
||||
if (!irq_iommu) {
|
||||
spin_unlock(&irq_2_ir_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
iommu = irq_2_iommu[irq].iommu;
|
||||
iommu = irq_iommu->iommu;
|
||||
|
||||
index = irq_2_iommu[irq].irte_index + irq_2_iommu[irq].sub_handle;
|
||||
index = irq_iommu->irte_index + irq_iommu->sub_handle;
|
||||
irte = &iommu->ir_table->base[index];
|
||||
|
||||
if (!irq_2_iommu[irq].sub_handle) {
|
||||
for (i = 0; i < (1 << irq_2_iommu[irq].irte_mask); i++)
|
||||
if (!irq_iommu->sub_handle) {
|
||||
for (i = 0; i < (1 << irq_iommu->irte_mask); i++)
|
||||
set_64bit((unsigned long *)irte, 0);
|
||||
qi_flush_iec(iommu, index, irq_2_iommu[irq].irte_mask);
|
||||
qi_flush_iec(iommu, index, irq_iommu->irte_mask);
|
||||
}
|
||||
|
||||
irq_2_iommu[irq].iommu = NULL;
|
||||
irq_2_iommu[irq].irte_index = 0;
|
||||
irq_2_iommu[irq].sub_handle = 0;
|
||||
irq_2_iommu[irq].irte_mask = 0;
|
||||
irq_iommu->iommu = NULL;
|
||||
irq_iommu->irte_index = 0;
|
||||
irq_iommu->sub_handle = 0;
|
||||
irq_iommu->irte_mask = 0;
|
||||
|
||||
spin_unlock(&irq_2_ir_lock);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue