aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@suse.com>2013-04-15 10:33:48 +0200
committerJan Beulich <jbeulich@suse.com>2013-04-15 10:33:48 +0200
commit6a727d6be892ea5ff818446d96974bebdf8ac3a2 (patch)
tree7b167dd6266b4c5b4824a496c8e7405fba05f489 /xen/arch/x86
parent887885c17ada9c571a7a2cd71410876448d0610a (diff)
downloadxen-6a727d6be892ea5ff818446d96974bebdf8ac3a2.tar.gz
xen-6a727d6be892ea5ff818446d96974bebdf8ac3a2.tar.bz2
xen-6a727d6be892ea5ff818446d96974bebdf8ac3a2.zip
IOMMU: allow MSI message to IRTE propagation to fail
With the need to allocate multiple contiguous IRTEs for multi-vector MSI, the chance of failure here increases. While on the AMD side there's no allocation of IRTEs at present at all (and hence no way for this allocation to fail, which is going to change with a later patch in this series), VT-d already ignores an eventual error here, which this patch fixes. Signed-off-by: Jan Beulich <jbeulich@suse.com> Acked-by: "Zhang, Xiantao" <xiantao.zhang@intel.com>
Diffstat (limited to 'xen/arch/x86')
-rw-r--r--xen/arch/x86/hpet.c20
-rw-r--r--xen/arch/x86/irq.c10
-rw-r--r--xen/arch/x86/msi.c22
3 files changed, 35 insertions, 17 deletions
diff --git a/xen/arch/x86/hpet.c b/xen/arch/x86/hpet.c
index 14041968a7..946d133655 100644
--- a/xen/arch/x86/hpet.c
+++ b/xen/arch/x86/hpet.c
@@ -254,13 +254,22 @@ static void hpet_msi_mask(struct irq_desc *desc)
ch->msi.msi_attrib.masked = 1;
}
-static void hpet_msi_write(struct hpet_event_channel *ch, struct msi_msg *msg)
+static int hpet_msi_write(struct hpet_event_channel *ch, struct msi_msg *msg)
{
ch->msi.msg = *msg;
+
if ( iommu_intremap )
- iommu_update_ire_from_msi(&ch->msi, msg);
+ {
+ int rc = iommu_update_ire_from_msi(&ch->msi, msg);
+
+ if ( rc )
+ return rc;
+ }
+
hpet_write32(msg->data, HPET_Tn_ROUTE(ch->idx));
hpet_write32(msg->address_lo, HPET_Tn_ROUTE(ch->idx) + 4);
+
+ return 0;
}
static void __maybe_unused
@@ -318,12 +327,12 @@ static hw_irq_controller hpet_msi_type = {
.set_affinity = hpet_msi_set_affinity,
};
-static void __hpet_setup_msi_irq(struct irq_desc *desc)
+static int __hpet_setup_msi_irq(struct irq_desc *desc)
{
struct msi_msg msg;
msi_compose_msg(desc, &msg);
- hpet_msi_write(desc->action->dev_id, &msg);
+ return hpet_msi_write(desc->action->dev_id, &msg);
}
static int __init hpet_setup_msi_irq(struct hpet_event_channel *ch)
@@ -347,6 +356,8 @@ static int __init hpet_setup_msi_irq(struct hpet_event_channel *ch)
desc->handler = &hpet_msi_type;
ret = request_irq(ch->msi.irq, hpet_interrupt_handler, 0, "HPET", ch);
+ if ( ret >= 0 )
+ ret = __hpet_setup_msi_irq(desc);
if ( ret < 0 )
{
if ( iommu_intremap )
@@ -354,7 +365,6 @@ static int __init hpet_setup_msi_irq(struct hpet_event_channel *ch)
return ret;
}
- __hpet_setup_msi_irq(desc);
desc->msi_desc = &ch->msi;
return 0;
diff --git a/xen/arch/x86/irq.c b/xen/arch/x86/irq.c
index dffb33a231..fa6b9a2e31 100644
--- a/xen/arch/x86/irq.c
+++ b/xen/arch/x86/irq.c
@@ -1938,7 +1938,14 @@ int map_domain_pirq(
if ( desc->handler != &no_irq_type )
dprintk(XENLOG_G_ERR, "dom%d: irq %d in use\n",
d->domain_id, irq);
- setup_msi_handler(desc, msi_desc);
+
+ ret = setup_msi_irq(desc, msi_desc);
+ if ( ret )
+ {
+ spin_unlock_irqrestore(&desc->lock, flags);
+ pci_disable_msi(msi_desc);
+ goto done;
+ }
if ( opt_irq_vector_map == OPT_IRQ_VECTOR_MAP_PERDEV
&& !desc->arch.used_vectors )
@@ -1954,7 +1961,6 @@ int map_domain_pirq(
}
set_domain_irq_pirq(d, irq, info);
- setup_msi_irq(desc);
spin_unlock_irqrestore(&desc->lock, flags);
}
else
diff --git a/xen/arch/x86/msi.c b/xen/arch/x86/msi.c
index 6cc8f7acab..36bed2953e 100644
--- a/xen/arch/x86/msi.c
+++ b/xen/arch/x86/msi.c
@@ -214,14 +214,18 @@ static void read_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
iommu_read_msi_from_ire(entry, msg);
}
-static void write_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
+static int write_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
{
entry->msg = *msg;
if ( iommu_intremap )
{
+ int rc;
+
ASSERT(msg != &entry->msg);
- iommu_update_ire_from_msi(entry, msg);
+ rc = iommu_update_ire_from_msi(entry, msg);
+ if ( rc )
+ return rc;
}
switch ( entry->msi_attrib.type )
@@ -264,6 +268,8 @@ static void write_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
default:
BUG();
}
+
+ return 0;
}
void set_msi_affinity(struct irq_desc *desc, const cpumask_t *mask)
@@ -464,19 +470,15 @@ static struct msi_desc* alloc_msi_entry(void)
return entry;
}
-void setup_msi_handler(struct irq_desc *desc, struct msi_desc *msidesc)
+int setup_msi_irq(struct irq_desc *desc, struct msi_desc *msidesc)
{
+ struct msi_msg msg;
+
desc->msi_desc = msidesc;
desc->handler = msi_maskable_irq(msidesc) ? &pci_msi_maskable
: &pci_msi_nonmaskable;
-}
-
-void setup_msi_irq(struct irq_desc *desc)
-{
- struct msi_msg msg;
-
msi_compose_msg(desc, &msg);
- write_msi_msg(desc->msi_desc, &msg);
+ return write_msi_msg(msidesc, &msg);
}
int msi_free_irq(struct msi_desc *entry)