Merge commit 'konrad/stable/xen-pcifront-0.8.2' into 2.6.36-rc8-initial-domain-v6

This commit is contained in:
Stefano Stabellini 2010-10-22 21:24:06 +01:00
commit 67ba37293e
122 changed files with 3944 additions and 2270 deletions

View file

@ -40,6 +40,27 @@ config PCI_STUB
When in doubt, say N.
config XEN_PCIDEV_FRONTEND
tristate "Xen PCI Frontend"
depends on PCI && X86 && XEN
select HOTPLUG
select PCI_XEN
default y
help
The PCI device frontend driver allows the kernel to import arbitrary
PCI devices from a PCI backend to support PCI driver domains.
config XEN_PCIDEV_FE_DEBUG
bool "Xen PCI Frontend debugging"
depends on XEN_PCIDEV_FRONTEND && PCI_DEBUG
help
Say Y here if you want the Xen PCI frontend to produce a bunch of debug
messages to the system log. Select this if you are having a
problem with Xen PCI frontend support and want to see more of what is
going on.
When in doubt, say N.
config HT_IRQ
bool "Interrupts on hypertransport devices"
default y

View file

@ -65,6 +65,8 @@ obj-$(CONFIG_PCI_SYSCALL) += syscall.o
obj-$(CONFIG_PCI_STUB) += pci-stub.o
obj-$(CONFIG_XEN_PCIDEV_FRONTEND) += xen-pcifront.o
ifeq ($(CONFIG_PCI_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG
endif

View file

@ -299,6 +299,7 @@ void pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *),
}
up_read(&pci_bus_sem);
}
EXPORT_SYMBOL_GPL(pci_walk_bus);
EXPORT_SYMBOL(pci_bus_alloc_resource);
EXPORT_SYMBOL_GPL(pci_bus_add_device);

View file

@ -1221,9 +1221,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 +1234,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);

View file

@ -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;
struct ht_irq_cfg *cfg = irq_data_get_irq_data(data);
struct ht_irq_msg msg = cfg->msg;
cfg = get_irq_data(irq);
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;
struct ht_irq_cfg *cfg = irq_data_get_irq_data(data);
struct ht_irq_msg msg = cfg->msg;
cfg = get_irq_data(irq);
msg = cfg->msg;
msg.address_lo &= ~1;
write_ht_irq_msg(irq, &msg);
write_ht_irq_msg(data->irq, &msg);
}
/**

View file

@ -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)
static struct irq_2_iommu *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)
{
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,21 +75,15 @@ 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)
if (!count || !irq_iommu)
return -1;
#ifndef CONFIG_SPARSE_IRQ
/* protect irq_2_iommu_alloc later */
if (irq >= nr_irqs)
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;
if (!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;
}
*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;
if (!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;
}
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;
if (!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;
}
rc = clear_entries(irq_iommu);

View file

@ -35,7 +35,12 @@ int arch_msi_check_device(struct pci_dev *dev, int nvec, int type)
#endif
#ifndef arch_setup_msi_irqs
int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
# define arch_setup_msi_irqs default_setup_msi_irqs
# define HAVE_DEFAULT_MSI_SETUP_IRQS
#endif
#ifdef HAVE_DEFAULT_MSI_SETUP_IRQS
int default_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
{
struct msi_desc *entry;
int ret;
@ -60,7 +65,12 @@ int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
#endif
#ifndef arch_teardown_msi_irqs
void arch_teardown_msi_irqs(struct pci_dev *dev)
# define arch_teardown_msi_irqs default_teardown_msi_irqs
# define HAVE_DEFAULT_MSI_TEARDOWN_IRQS
#endif
#ifdef HAVE_DEFAULT_MSI_TEARDOWN_IRQS
void default_teardown_msi_irqs(struct pci_dev *dev)
{
struct msi_desc *entry;
@ -170,33 +180,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 +235,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 +252,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 +296,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)

1148
drivers/pci/xen-pcifront.c Normal file

File diff suppressed because it is too large Load diff