summaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/dmar.c14
-rw-r--r--drivers/pci/hotplug/cpqphp_sysfs.c13
-rw-r--r--drivers/pci/htirq.c22
-rw-r--r--drivers/pci/intr_remapping.c212
-rw-r--r--drivers/pci/msi.c38
-rw-r--r--drivers/pci/quirks.c20
6 files changed, 87 insertions, 232 deletions
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c
index 0a19708074c2..0157708d474d 100644
--- a/drivers/pci/dmar.c
+++ b/drivers/pci/dmar.c
@@ -36,6 +36,7 @@
#include <linux/tboot.h>
#include <linux/dmi.h>
#include <linux/slab.h>
+#include <asm/iommu_table.h>
#define PREFIX "DMAR: "
@@ -687,7 +688,7 @@ failed:
return 0;
}
-void __init detect_intel_iommu(void)
+int __init detect_intel_iommu(void)
{
int ret;
@@ -723,6 +724,8 @@ void __init detect_intel_iommu(void)
}
early_acpi_os_unmap_memory(dmar_tbl, dmar_tbl_size);
dmar_tbl = NULL;
+
+ return ret ? 1 : -ENODEV;
}
@@ -1221,9 +1224,9 @@ const char *dmar_get_fault_reason(u8 fault_reason, int *fault_type)
}
}
-void dmar_msi_unmask(unsigned int irq)
+void dmar_msi_unmask(struct irq_data *data)
{
- struct intel_iommu *iommu = get_irq_data(irq);
+ struct intel_iommu *iommu = irq_data_get_irq_data(data);
unsigned long flag;
/* unmask it */
@@ -1234,10 +1237,10 @@ void dmar_msi_unmask(unsigned int irq)
spin_unlock_irqrestore(&iommu->register_lock, flag);
}
-void dmar_msi_mask(unsigned int irq)
+void dmar_msi_mask(struct irq_data *data)
{
unsigned long flag;
- struct intel_iommu *iommu = get_irq_data(irq);
+ struct intel_iommu *iommu = irq_data_get_irq_data(data);
/* mask it */
spin_lock_irqsave(&iommu->register_lock, flag);
@@ -1455,3 +1458,4 @@ int __init dmar_ir_support(void)
return 0;
return dmar->flags & 0x1;
}
+IOMMU_INIT_POST(detect_intel_iommu);
diff --git a/drivers/pci/hotplug/cpqphp_sysfs.c b/drivers/pci/hotplug/cpqphp_sysfs.c
index 56215322930a..4cb30447a486 100644
--- a/drivers/pci/hotplug/cpqphp_sysfs.c
+++ b/drivers/pci/hotplug/cpqphp_sysfs.c
@@ -34,10 +34,11 @@
#include <linux/workqueue.h>
#include <linux/pci.h>
#include <linux/pci_hotplug.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/debugfs.h>
#include "cpqphp.h"
+static DEFINE_MUTEX(cpqphp_mutex);
static int show_ctrl (struct controller *ctrl, char *buf)
{
char *out = buf;
@@ -147,7 +148,7 @@ static int open(struct inode *inode, struct file *file)
struct ctrl_dbg *dbg;
int retval = -ENOMEM;
- lock_kernel();
+ mutex_lock(&cpqphp_mutex);
dbg = kmalloc(sizeof(*dbg), GFP_KERNEL);
if (!dbg)
goto exit;
@@ -160,7 +161,7 @@ static int open(struct inode *inode, struct file *file)
file->private_data = dbg;
retval = 0;
exit:
- unlock_kernel();
+ mutex_unlock(&cpqphp_mutex);
return retval;
}
@@ -169,7 +170,7 @@ static loff_t lseek(struct file *file, loff_t off, int whence)
struct ctrl_dbg *dbg;
loff_t new = -1;
- lock_kernel();
+ mutex_lock(&cpqphp_mutex);
dbg = file->private_data;
switch (whence) {
@@ -181,10 +182,10 @@ static loff_t lseek(struct file *file, loff_t off, int whence)
break;
}
if (new < 0 || new > dbg->size) {
- unlock_kernel();
+ mutex_unlock(&cpqphp_mutex);
return -EINVAL;
}
- unlock_kernel();
+ mutex_unlock(&cpqphp_mutex);
return (file->f_pos = new);
}
diff --git a/drivers/pci/htirq.c b/drivers/pci/htirq.c
index 98abf8b91294..834842aa5bbf 100644
--- a/drivers/pci/htirq.c
+++ b/drivers/pci/htirq.c
@@ -57,28 +57,22 @@ void fetch_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg)
*msg = cfg->msg;
}
-void mask_ht_irq(unsigned int irq)
+void mask_ht_irq(struct irq_data *data)
{
- struct ht_irq_cfg *cfg;
- struct ht_irq_msg msg;
-
- cfg = get_irq_data(irq);
+ struct ht_irq_cfg *cfg = irq_data_get_irq_data(data);
+ struct ht_irq_msg msg = cfg->msg;
- msg = cfg->msg;
msg.address_lo |= 1;
- write_ht_irq_msg(irq, &msg);
+ write_ht_irq_msg(data->irq, &msg);
}
-void unmask_ht_irq(unsigned int irq)
+void unmask_ht_irq(struct irq_data *data)
{
- struct ht_irq_cfg *cfg;
- struct ht_irq_msg msg;
-
- cfg = get_irq_data(irq);
+ struct ht_irq_cfg *cfg = irq_data_get_irq_data(data);
+ struct ht_irq_msg msg = cfg->msg;
- msg = cfg->msg;
msg.address_lo &= ~1;
- write_ht_irq_msg(irq, &msg);
+ write_ht_irq_msg(data->irq, &msg);
}
/**
diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c
index fd1d2867cdcc..ec87cd66f3eb 100644
--- a/drivers/pci/intr_remapping.c
+++ b/drivers/pci/intr_remapping.c
@@ -46,109 +46,24 @@ static __init int setup_intremap(char *str)
}
early_param("intremap", setup_intremap);
-struct irq_2_iommu {
- struct intel_iommu *iommu;
- u16 irte_index;
- u16 sub_handle;
- u8 irte_mask;
-};
-
-#ifdef CONFIG_GENERIC_HARDIRQS
-static struct irq_2_iommu *get_one_free_irq_2_iommu(int node)
-{
- struct irq_2_iommu *iommu;
-
- iommu = kzalloc_node(sizeof(*iommu), GFP_ATOMIC, node);
- printk(KERN_DEBUG "alloc irq_2_iommu on node %d\n", node);
-
- return iommu;
-}
-
-static struct irq_2_iommu *irq_2_iommu(unsigned int irq)
-{
- struct irq_desc *desc;
-
- desc = irq_to_desc(irq);
-
- if (WARN_ON_ONCE(!desc))
- return NULL;
-
- return desc->irq_2_iommu;
-}
-
-static struct irq_2_iommu *irq_2_iommu_alloc(unsigned int irq)
-{
- struct irq_desc *desc;
- struct irq_2_iommu *irq_iommu;
-
- desc = irq_to_desc(irq);
- if (!desc) {
- printk(KERN_INFO "can not get irq_desc for %d\n", irq);
- return NULL;
- }
-
- irq_iommu = desc->irq_2_iommu;
-
- if (!irq_iommu)
- desc->irq_2_iommu = get_one_free_irq_2_iommu(irq_node(irq));
-
- return desc->irq_2_iommu;
-}
-
-#else /* !CONFIG_SPARSE_IRQ */
-
-static struct irq_2_iommu irq_2_iommuX[NR_IRQS];
-
-static struct irq_2_iommu *irq_2_iommu(unsigned int irq)
-{
- if (irq < nr_irqs)
- return &irq_2_iommuX[irq];
-
- return NULL;
-}
-static struct irq_2_iommu *irq_2_iommu_alloc(unsigned int irq)
-{
- return irq_2_iommu(irq);
-}
-#endif
-
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)
+static struct irq_2_iommu *irq_2_iommu(unsigned int irq)
{
- return valid_irq_2_iommu(irq) != NULL;
+ struct irq_cfg *cfg = get_irq_chip_data(irq);
+ return cfg ? &cfg->irq_2_iommu : NULL;
}
int get_irte(int irq, struct irte *entry)
{
- int index;
- struct irq_2_iommu *irq_iommu;
+ struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
unsigned long flags;
+ int index;
- if (!entry)
+ if (!entry || !irq_iommu)
return -1;
spin_lock_irqsave(&irq_2_ir_lock, flags);
- irq_iommu = valid_irq_2_iommu(irq);
- if (!irq_iommu) {
- spin_unlock_irqrestore(&irq_2_ir_lock, flags);
- return -1;
- }
index = irq_iommu->irte_index + irq_iommu->sub_handle;
*entry = *(irq_iommu->iommu->ir_table->base + index);
@@ -160,20 +75,14 @@ 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;
+ struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
u16 index, start_index;
unsigned int mask = 0;
unsigned long flags;
int i;
- if (!count)
- return -1;
-
-#ifndef CONFIG_SPARSE_IRQ
- /* protect irq_2_iommu_alloc later */
- if (irq >= nr_irqs)
+ if (!count || !irq_iommu)
return -1;
-#endif
/*
* start the IRTE search from index 0.
@@ -214,13 +123,6 @@ int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
for (i = index; i < index + count; i++)
table->base[i].present = 1;
- irq_iommu = irq_2_iommu_alloc(irq);
- if (!irq_iommu) {
- spin_unlock_irqrestore(&irq_2_ir_lock, flags);
- printk(KERN_ERR "can't allocate irq_2_iommu\n");
- return -1;
- }
-
irq_iommu->iommu = iommu;
irq_iommu->irte_index = index;
irq_iommu->sub_handle = 0;
@@ -244,17 +146,14 @@ static int 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;
+ struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
unsigned long flags;
+ int index;
- spin_lock_irqsave(&irq_2_ir_lock, flags);
- irq_iommu = valid_irq_2_iommu(irq);
- if (!irq_iommu) {
- spin_unlock_irqrestore(&irq_2_ir_lock, flags);
+ if (!irq_iommu)
return -1;
- }
+ spin_lock_irqsave(&irq_2_ir_lock, flags);
*sub_handle = irq_iommu->sub_handle;
index = irq_iommu->irte_index;
spin_unlock_irqrestore(&irq_2_ir_lock, flags);
@@ -263,18 +162,13 @@ int map_irq_to_irte_handle(int irq, u16 *sub_handle)
int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle)
{
- struct irq_2_iommu *irq_iommu;
+ struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
unsigned long flags;
- spin_lock_irqsave(&irq_2_ir_lock, flags);
-
- irq_iommu = irq_2_iommu_alloc(irq);
-
- if (!irq_iommu) {
- spin_unlock_irqrestore(&irq_2_ir_lock, flags);
- printk(KERN_ERR "can't allocate irq_2_iommu\n");
+ if (!irq_iommu)
return -1;
- }
+
+ spin_lock_irqsave(&irq_2_ir_lock, flags);
irq_iommu->iommu = iommu;
irq_iommu->irte_index = index;
@@ -286,43 +180,18 @@ int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle)
return 0;
}
-int clear_irte_irq(int irq, struct intel_iommu *iommu, u16 index)
-{
- struct irq_2_iommu *irq_iommu;
- unsigned long flags;
-
- spin_lock_irqsave(&irq_2_ir_lock, flags);
- irq_iommu = valid_irq_2_iommu(irq);
- if (!irq_iommu) {
- spin_unlock_irqrestore(&irq_2_ir_lock, flags);
- return -1;
- }
-
- irq_iommu->iommu = NULL;
- irq_iommu->irte_index = 0;
- irq_iommu->sub_handle = 0;
- irq_2_iommu(irq)->irte_mask = 0;
-
- spin_unlock_irqrestore(&irq_2_ir_lock, flags);
-
- return 0;
-}
-
int modify_irte(int irq, struct irte *irte_modified)
{
- int rc;
- int index;
- struct irte *irte;
+ struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
struct intel_iommu *iommu;
- struct irq_2_iommu *irq_iommu;
unsigned long flags;
+ struct irte *irte;
+ int rc, index;
- spin_lock_irqsave(&irq_2_ir_lock, flags);
- irq_iommu = valid_irq_2_iommu(irq);
- if (!irq_iommu) {
- spin_unlock_irqrestore(&irq_2_ir_lock, flags);
+ if (!irq_iommu)
return -1;
- }
+
+ spin_lock_irqsave(&irq_2_ir_lock, flags);
iommu = irq_iommu->iommu;
@@ -339,31 +208,6 @@ int modify_irte(int irq, struct irte *irte_modified)
return rc;
}
-int flush_irte(int irq)
-{
- int rc;
- int index;
- struct intel_iommu *iommu;
- struct irq_2_iommu *irq_iommu;
- unsigned long flags;
-
- spin_lock_irqsave(&irq_2_ir_lock, flags);
- irq_iommu = valid_irq_2_iommu(irq);
- if (!irq_iommu) {
- spin_unlock_irqrestore(&irq_2_ir_lock, flags);
- return -1;
- }
-
- iommu = irq_iommu->iommu;
-
- index = irq_iommu->irte_index + irq_iommu->sub_handle;
-
- rc = qi_flush_iec(iommu, index, irq_iommu->irte_mask);
- spin_unlock_irqrestore(&irq_2_ir_lock, flags);
-
- return rc;
-}
-
struct intel_iommu *map_hpet_to_ir(u8 hpet_id)
{
int i;
@@ -420,16 +264,14 @@ static int clear_entries(struct irq_2_iommu *irq_iommu)
int free_irte(int irq)
{
- int rc = 0;
- struct irq_2_iommu *irq_iommu;
+ struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
unsigned long flags;
+ int rc;
- spin_lock_irqsave(&irq_2_ir_lock, flags);
- irq_iommu = valid_irq_2_iommu(irq);
- if (!irq_iommu) {
- spin_unlock_irqrestore(&irq_2_ir_lock, flags);
+ if (!irq_iommu)
return -1;
- }
+
+ spin_lock_irqsave(&irq_2_ir_lock, flags);
rc = clear_entries(irq_iommu);
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 69b7be33b3a2..5fcf5aec680f 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -170,33 +170,31 @@ static void msix_mask_irq(struct msi_desc *desc, u32 flag)
desc->masked = __msix_mask_irq(desc, flag);
}
-static void msi_set_mask_bit(unsigned irq, u32 flag)
+static void msi_set_mask_bit(struct irq_data *data, u32 flag)
{
- struct msi_desc *desc = get_irq_msi(irq);
+ struct msi_desc *desc = irq_data_get_msi(data);
if (desc->msi_attrib.is_msix) {
msix_mask_irq(desc, flag);
readl(desc->mask_base); /* Flush write to device */
} else {
- unsigned offset = irq - desc->dev->irq;
+ unsigned offset = data->irq - desc->dev->irq;
msi_mask_irq(desc, 1 << offset, flag << offset);
}
}
-void mask_msi_irq(unsigned int irq)
+void mask_msi_irq(struct irq_data *data)
{
- msi_set_mask_bit(irq, 1);
+ msi_set_mask_bit(data, 1);
}
-void unmask_msi_irq(unsigned int irq)
+void unmask_msi_irq(struct irq_data *data)
{
- msi_set_mask_bit(irq, 0);
+ msi_set_mask_bit(data, 0);
}
-void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg)
+void __read_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
{
- struct msi_desc *entry = get_irq_desc_msi(desc);
-
BUG_ON(entry->dev->current_state != PCI_D0);
if (entry->msi_attrib.is_msix) {
@@ -227,15 +225,13 @@ void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg)
void read_msi_msg(unsigned int irq, struct msi_msg *msg)
{
- struct irq_desc *desc = irq_to_desc(irq);
+ struct msi_desc *entry = get_irq_msi(irq);
- read_msi_msg_desc(desc, msg);
+ __read_msi_msg(entry, msg);
}
-void get_cached_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg)
+void __get_cached_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
{
- struct msi_desc *entry = get_irq_desc_msi(desc);
-
/* Assert that the cache is valid, assuming that
* valid messages are not all-zeroes. */
BUG_ON(!(entry->msg.address_hi | entry->msg.address_lo |
@@ -246,15 +242,13 @@ void get_cached_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg)
void get_cached_msi_msg(unsigned int irq, struct msi_msg *msg)
{
- struct irq_desc *desc = irq_to_desc(irq);
+ struct msi_desc *entry = get_irq_msi(irq);
- get_cached_msi_msg_desc(desc, msg);
+ __get_cached_msi_msg(entry, msg);
}
-void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg)
+void __write_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
{
- struct msi_desc *entry = get_irq_desc_msi(desc);
-
if (entry->dev->current_state != PCI_D0) {
/* Don't touch the hardware now */
} else if (entry->msi_attrib.is_msix) {
@@ -292,9 +286,9 @@ void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg)
void write_msi_msg(unsigned int irq, struct msi_msg *msg)
{
- struct irq_desc *desc = irq_to_desc(irq);
+ struct msi_desc *entry = get_irq_msi(irq);
- write_msi_msg_desc(desc, msg);
+ __write_msi_msg(entry, msg);
}
static void free_msi_irqs(struct pci_dev *dev)
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 89ed181cd90c..857ae01734a6 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -163,6 +163,26 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_2, quirk_isa_d
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_3, quirk_isa_dma_hangs);
/*
+ * Intel NM10 "TigerPoint" LPC PM1a_STS.BM_STS must be clear
+ * for some HT machines to use C4 w/o hanging.
+ */
+static void __devinit quirk_tigerpoint_bm_sts(struct pci_dev *dev)
+{
+ u32 pmbase;
+ u16 pm1a;
+
+ pci_read_config_dword(dev, 0x40, &pmbase);
+ pmbase = pmbase & 0xff80;
+ pm1a = inw(pmbase);
+
+ if (pm1a & 0x10) {
+ dev_info(&dev->dev, FW_BUG "TigerPoint LPC.BM_STS cleared\n");
+ outw(0x10, pmbase);
+ }
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TGP_LPC, quirk_tigerpoint_bm_sts);
+
+/*
* Chipsets where PCI->PCI transfers vanish or hang
*/
static void __devinit quirk_nopcipci(struct pci_dev *dev)