aboutsummaryrefslogtreecommitdiffstats
path: root/xen/drivers/passthrough
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/drivers/passthrough
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/drivers/passthrough')
-rw-r--r--xen/drivers/passthrough/amd/iommu_intr.c35
-rw-r--r--xen/drivers/passthrough/iommu.c8
-rw-r--r--xen/drivers/passthrough/vtd/extern.h2
-rw-r--r--xen/drivers/passthrough/vtd/intremap.c6
4 files changed, 33 insertions, 18 deletions
diff --git a/xen/drivers/passthrough/amd/iommu_intr.c b/xen/drivers/passthrough/amd/iommu_intr.c
index 49ed3a2ab2..794304936b 100644
--- a/xen/drivers/passthrough/amd/iommu_intr.c
+++ b/xen/drivers/passthrough/amd/iommu_intr.c
@@ -17,6 +17,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <xen/err.h>
#include <xen/sched.h>
#include <xen/hvm/iommu.h>
#include <asm/amd-iommu.h>
@@ -359,25 +360,35 @@ done:
}
}
-void amd_iommu_msi_msg_update_ire(
+static struct amd_iommu *_find_iommu_for_device(int seg, int bdf)
+{
+ struct amd_iommu *iommu = find_iommu_for_device(seg, bdf);
+
+ if ( iommu )
+ return iommu;
+
+ list_for_each_entry ( iommu, &amd_iommu_head, list )
+ if ( iommu->seg == seg && iommu->bdf == bdf )
+ return NULL;
+
+ AMD_IOMMU_DEBUG("No IOMMU for MSI dev = %04x:%02x:%02x.%u\n",
+ seg, PCI_BUS(bdf), PCI_SLOT(bdf), PCI_FUNC(bdf));
+ return ERR_PTR(-EINVAL);
+}
+
+int amd_iommu_msi_msg_update_ire(
struct msi_desc *msi_desc, struct msi_msg *msg)
{
struct pci_dev *pdev = msi_desc->dev;
int bdf, seg;
struct amd_iommu *iommu;
- if ( !iommu_intremap )
- return;
-
bdf = pdev ? PCI_BDF2(pdev->bus, pdev->devfn) : hpet_sbdf.bdf;
seg = pdev ? pdev->seg : hpet_sbdf.seg;
- iommu = find_iommu_for_device(seg, bdf);
- if ( !iommu )
- {
- AMD_IOMMU_DEBUG("Fail to find iommu for MSI device id = %#x\n", bdf);
- return;
- }
+ iommu = _find_iommu_for_device(seg, bdf);
+ if ( IS_ERR_OR_NULL(iommu) )
+ return PTR_ERR(iommu);
if ( msi_desc->remap_index >= 0 )
{
@@ -395,7 +406,7 @@ void amd_iommu_msi_msg_update_ire(
}
if ( !msg )
- return;
+ return 0;
do {
update_intremap_entry_from_msi_msg(iommu, bdf, &msi_desc->remap_index,
@@ -404,6 +415,8 @@ void amd_iommu_msi_msg_update_ire(
break;
bdf += pdev->phantom_stride;
} while ( PCI_SLOT(bdf) == PCI_SLOT(pdev->devfn) );
+
+ return 0;
}
void amd_iommu_read_msi_from_ire(
diff --git a/xen/drivers/passthrough/iommu.c b/xen/drivers/passthrough/iommu.c
index 2db2e17494..c5906abd88 100644
--- a/xen/drivers/passthrough/iommu.c
+++ b/xen/drivers/passthrough/iommu.c
@@ -548,18 +548,20 @@ void iommu_update_ire_from_apic(
const struct iommu_ops *ops = iommu_get_ops();
ops->update_ire_from_apic(apic, reg, value);
}
-void iommu_update_ire_from_msi(
+
+int iommu_update_ire_from_msi(
struct msi_desc *msi_desc, struct msi_msg *msg)
{
const struct iommu_ops *ops = iommu_get_ops();
- ops->update_ire_from_msi(msi_desc, msg);
+ return iommu_intremap ? ops->update_ire_from_msi(msi_desc, msg) : 0;
}
void iommu_read_msi_from_ire(
struct msi_desc *msi_desc, struct msi_msg *msg)
{
const struct iommu_ops *ops = iommu_get_ops();
- ops->read_msi_from_ire(msi_desc, msg);
+ if ( iommu_intremap )
+ ops->read_msi_from_ire(msi_desc, msg);
}
unsigned int iommu_read_apic_from_ire(unsigned int apic, unsigned int reg)
diff --git a/xen/drivers/passthrough/vtd/extern.h b/xen/drivers/passthrough/vtd/extern.h
index ec4b8cf002..14cd90ee98 100644
--- a/xen/drivers/passthrough/vtd/extern.h
+++ b/xen/drivers/passthrough/vtd/extern.h
@@ -90,7 +90,7 @@ void io_apic_write_remap_rte(unsigned int apic,
struct msi_desc;
struct msi_msg;
void msi_msg_read_remap_rte(struct msi_desc *, struct msi_msg *);
-void msi_msg_write_remap_rte(struct msi_desc *, struct msi_msg *);
+int msi_msg_write_remap_rte(struct msi_desc *, struct msi_msg *);
int intel_setup_hpet_msi(struct msi_desc *);
diff --git a/xen/drivers/passthrough/vtd/intremap.c b/xen/drivers/passthrough/vtd/intremap.c
index 0dc1788b24..880f15eab0 100644
--- a/xen/drivers/passthrough/vtd/intremap.c
+++ b/xen/drivers/passthrough/vtd/intremap.c
@@ -653,7 +653,7 @@ void msi_msg_read_remap_rte(
remap_entry_to_msi_msg(drhd->iommu, msg);
}
-void msi_msg_write_remap_rte(
+int msi_msg_write_remap_rte(
struct msi_desc *msi_desc, struct msi_msg *msg)
{
struct pci_dev *pdev = msi_desc->dev;
@@ -661,8 +661,8 @@ void msi_msg_write_remap_rte(
drhd = pdev ? acpi_find_matched_drhd_unit(pdev)
: hpet_to_drhd(msi_desc->hpet_id);
- if ( drhd )
- msi_msg_to_remap_entry(drhd->iommu, pdev, msi_desc, msg);
+ return drhd ? msi_msg_to_remap_entry(drhd->iommu, pdev, msi_desc, msg)
+ : -EINVAL;
}
int __init intel_setup_hpet_msi(struct msi_desc *msi_desc)