2013-10-29 11:34:19

by Bharat Bhushan

[permalink] [raw]
Subject: [PATCH 1/5 RFC] pci:msi: add weak function for returning msi region info

In Aperture type of IOMMU (like FSL PAMU), VFIO-iommu system need to know
the MSI region to map its window in h/w. This patch just defines the
required weak functions only and will be used by followup patches.

Signed-off-by: Bharat Bhushan <[email protected]>
---
drivers/pci/msi.c | 22 ++++++++++++++++++++++
include/linux/msi.h | 14 ++++++++++++++
2 files changed, 36 insertions(+), 0 deletions(-)

diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index d5f90d6..2643a29 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -67,6 +67,28 @@ int __weak arch_msi_check_device(struct pci_dev *dev, int nvec, int type)
return chip->check_device(chip, dev, nvec, type);
}

+int __weak arch_msi_get_region_count(void)
+{
+ return 0;
+}
+
+int __weak arch_msi_get_region(int region_num, struct msi_region *region)
+{
+ return 0;
+}
+
+int msi_get_region_count(void)
+{
+ return arch_msi_get_region_count();
+}
+EXPORT_SYMBOL(msi_get_region_count);
+
+int msi_get_region(int region_num, struct msi_region *region)
+{
+ return arch_msi_get_region(region_num, region);
+}
+EXPORT_SYMBOL(msi_get_region);
+
int __weak arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
{
struct msi_desc *entry;
diff --git a/include/linux/msi.h b/include/linux/msi.h
index b17ead8..0deedb4 100644
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -51,6 +51,18 @@ struct msi_desc {
};

/*
+ * This structure is used to get
+ * - physical address
+ * - size
+ * of a msi region
+ */
+struct msi_region {
+ int region_num; /* MSI region number */
+ dma_addr_t addr; /* Address of MSI region */
+ size_t size; /* Size of MSI region */
+};
+
+/*
* The arch hooks to setup up msi irqs. Those functions are
* implemented as weak symbols so that they /can/ be overriden by
* architecture specific code if needed.
@@ -64,6 +76,8 @@ void arch_restore_msi_irqs(struct pci_dev *dev, int irq);

void default_teardown_msi_irqs(struct pci_dev *dev);
void default_restore_msi_irqs(struct pci_dev *dev, int irq);
+int arch_msi_get_region_count(void);
+int arch_msi_get_region(int region_num, struct msi_region *region);

struct msi_chip {
struct module *owner;
--
1.7.0.4


2013-10-29 11:34:23

by Bharat Bhushan

[permalink] [raw]
Subject: [PATCH 4/5 RFC] pci: msi: expose msi region information functions

So by now we have defined all the interfaces for getting the msi region,
this patch expose the interface to linux subsystem. These will be used by
vfio subsystem for setting up iommu for MSI interrupt of direct assignment
devices.

Signed-off-by: Bharat Bhushan <[email protected]>
---
include/linux/pci.h | 13 +++++++++++++
1 files changed, 13 insertions(+), 0 deletions(-)

diff --git a/include/linux/pci.h b/include/linux/pci.h
index da172f9..c587034 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1142,6 +1142,7 @@ struct msix_entry {
u16 entry; /* driver uses to specify entry, OS writes */
};

+struct msi_region;

#ifndef CONFIG_PCI_MSI
static inline int pci_enable_msi_block(struct pci_dev *dev, unsigned int nvec)
@@ -1184,6 +1185,16 @@ static inline int pci_msi_enabled(void)
{
return 0;
}
+
+static inline int msi_get_region_count(void)
+{
+ return 0;
+}
+
+static inline int msi_get_region(int region_num, struct msi_region *region)
+{
+ return 0;
+}
#else
int pci_enable_msi_block(struct pci_dev *dev, unsigned int nvec);
int pci_enable_msi_block_auto(struct pci_dev *dev, unsigned int *maxvec);
@@ -1196,6 +1207,8 @@ void pci_disable_msix(struct pci_dev *dev);
void msi_remove_pci_irq_vectors(struct pci_dev *dev);
void pci_restore_msi_state(struct pci_dev *dev);
int pci_msi_enabled(void);
+int msi_get_region_count(void);
+int msi_get_region(int region_num, struct msi_region *region);
#endif

#ifdef CONFIG_PCIEPORTBUS
--
1.7.0.4

2013-10-29 11:34:30

by Bharat Bhushan

[permalink] [raw]
Subject: [PATCH 3/5 RFC] powerpc: msi: Extend the msi region interface to get info from fsl_msi

The FSL MSI will provide the interface to get:
- Number of MSI regions (which is number of MSI banks for powerpc)
- Get the region address range: Physical page which have the
address/addresses used for generating MSI interrupt
and size of the page.

These are required to create IOMMU (Freescale PAMU) mapping for
devices which are directly assigned using VFIO.

Signed-off-by: Bharat Bhushan <[email protected]>
---
arch/powerpc/sysdev/fsl_msi.c | 42 +++++++++++++++++++++++++++++++++++-----
arch/powerpc/sysdev/fsl_msi.h | 11 ++++++++-
2 files changed, 45 insertions(+), 8 deletions(-)

diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c
index 77efbae..eeebbf0 100644
--- a/arch/powerpc/sysdev/fsl_msi.c
+++ b/arch/powerpc/sysdev/fsl_msi.c
@@ -109,6 +109,34 @@ static int fsl_msi_init_allocator(struct fsl_msi *msi_data)
return 0;
}

+static int fsl_msi_get_region_count(void)
+{
+ int count = 0;
+ struct fsl_msi *msi_data;
+
+ list_for_each_entry(msi_data, &msi_head, list)
+ count++;
+
+ return count;
+}
+
+static int fsl_msi_get_region(int region_num, struct msi_region *region)
+{
+ struct fsl_msi *msi_data;
+
+ list_for_each_entry(msi_data, &msi_head, list) {
+ if (msi_data->bank_index == region_num) {
+ region->region_num = msi_data->bank_index;
+ /* Setting PAGE_SIZE as MSIIR is a 4 byte register */
+ region->size = PAGE_SIZE;
+ region->addr = msi_data->msiir & ~(region->size - 1);
+ return 0;
+ }
+ }
+
+ return -ENODEV;
+}
+
static int fsl_msi_check_device(struct pci_dev *pdev, int nvec, int type)
{
if (type == PCI_CAP_ID_MSIX)
@@ -150,7 +178,8 @@ static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq,
if (reg && (len == sizeof(u64)))
address = be64_to_cpup(reg);
else
- address = fsl_pci_immrbar_base(hose) + msi_data->msiir_offset;
+ address = fsl_pci_immrbar_base(hose) +
+ (msi_data->msiir & 0xfffff);

msg->address_lo = lower_32_bits(address);
msg->address_hi = upper_32_bits(address);
@@ -393,6 +422,7 @@ static int fsl_of_msi_probe(struct platform_device *dev)
const struct fsl_msi_feature *features;
int len;
u32 offset;
+ static atomic_t bank_index = ATOMIC_INIT(-1);

match = of_match_device(fsl_of_msi_ids, &dev->dev);
if (!match)
@@ -436,18 +466,15 @@ static int fsl_of_msi_probe(struct platform_device *dev)
dev->dev.of_node->full_name);
goto error_out;
}
- msi->msiir_offset =
- features->msiir_offset + (res.start & 0xfffff);

/*
* First read the MSIIR/MSIIR1 offset from dts
* On failure use the hardcode MSIIR offset
*/
if (of_address_to_resource(dev->dev.of_node, 1, &msiir))
- msi->msiir_offset = features->msiir_offset +
- (res.start & MSIIR_OFFSET_MASK);
+ msi->msiir = res.start + features->msiir_offset;
else
- msi->msiir_offset = msiir.start & MSIIR_OFFSET_MASK;
+ msi->msiir = msiir.start;
}

msi->feature = features->fsl_pic_ip;
@@ -521,6 +548,7 @@ static int fsl_of_msi_probe(struct platform_device *dev)
}
}

+ msi->bank_index = atomic_inc_return(&bank_index);
list_add_tail(&msi->list, &msi_head);

/* The multiple setting ppc_md.setup_msi_irqs will not harm things */
@@ -528,6 +556,8 @@ static int fsl_of_msi_probe(struct platform_device *dev)
ppc_md.setup_msi_irqs = fsl_setup_msi_irqs;
ppc_md.teardown_msi_irqs = fsl_teardown_msi_irqs;
ppc_md.msi_check_device = fsl_msi_check_device;
+ ppc_md.msi_get_region_count = fsl_msi_get_region_count;
+ ppc_md.msi_get_region = fsl_msi_get_region;
} else if (ppc_md.setup_msi_irqs != fsl_setup_msi_irqs) {
dev_err(&dev->dev, "Different MSI driver already installed!\n");
err = -ENODEV;
diff --git a/arch/powerpc/sysdev/fsl_msi.h b/arch/powerpc/sysdev/fsl_msi.h
index df9aa9f..a2cc5a2 100644
--- a/arch/powerpc/sysdev/fsl_msi.h
+++ b/arch/powerpc/sysdev/fsl_msi.h
@@ -31,14 +31,21 @@ struct fsl_msi {
struct irq_domain *irqhost;

unsigned long cascade_irq;
-
- u32 msiir_offset; /* Offset of MSIIR, relative to start of CCSR */
+ phys_addr_t msiir; /* MSIIR Address in CCSR */
u32 ibs_shift; /* Shift of interrupt bit select */
u32 srs_shift; /* Shift of the shared interrupt register select */
void __iomem *msi_regs;
u32 feature;
int msi_virqs[NR_MSI_REG_MAX];

+ /*
+ * During probe each bank is assigned a index number.
+ * index number start from 0.
+ * Example MSI bank 1 = 0
+ * MSI bank 2 = 1, and so on.
+ */
+ int bank_index;
+
struct msi_bitmap bitmap;

struct list_head list; /* support multiple MSI banks */
--
1.7.0.4

2013-10-29 11:34:47

by Bharat Bhushan

[permalink] [raw]
Subject: [PATCH 5/5 RFC] vfio: setup iova-base for msi interrupts for vfio assigned device

PAMU (FSL IOMMU) has a concept of primary window and subwindows.
Primary window corresponds to the complete guest iova address space
(including MSI space), with respect to IOMMU_API this is termed as
geometry. IOVA Base of subwindow is determined from the number of
subwindows (configurable using iommu API).
MSI I/O page must be within the geometry and maximum supported
subwindows, so MSI IO-page is setup just after guest memory iova space.

This patch is for setting up MSI iova-base for vfio devices assigned
in msi subsystem, so that when msi-message will be composed then this
configured iova will be used.

According to this design vfio will make msi_set_iova() msi-API call to
setup iova for a device. MSI will keep track of iova-base of all device
under a msi-bank. When composing the MSI address and data this list will
be traversed, if device found in the list then device used by vfio and
its iova-base will be taken from here otherwise iova-base will be taken
as before.

This is a draft patch to describe the interface to setup iova in MSI
(what Alex Williamson proposed earlier on related patchset).
Currently I have bundled all changes in one patch to take initial
review comment on design. I will divide this in multiple logical
patches once this design is accepted.

Signed-off-by: Bharat Bhushan <[email protected]>
---
arch/powerpc/include/asm/machdep.h | 2 +
arch/powerpc/kernel/msi.c | 10 ++++++
arch/powerpc/sysdev/fsl_msi.c | 64 ++++++++++++++++++++++++++++++++++++
arch/powerpc/sysdev/fsl_msi.h | 10 ++++-
drivers/pci/msi.c | 12 +++++++
include/linux/pci.h | 8 ++++
6 files changed, 104 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
index 8d1b787..e87b806 100644
--- a/arch/powerpc/include/asm/machdep.h
+++ b/arch/powerpc/include/asm/machdep.h
@@ -132,6 +132,8 @@ struct machdep_calls {
/* Returns the requested region's address and size */
int (*msi_get_region)(int region_num,
struct msi_region *region);
+ int (*msi_set_iova)(struct pci_dev *pdev, int region_num,
+ dma_addr_t iova, bool set);
#endif

void (*restart)(char *cmd);
diff --git a/arch/powerpc/kernel/msi.c b/arch/powerpc/kernel/msi.c
index 1a67787..e2bd555 100644
--- a/arch/powerpc/kernel/msi.c
+++ b/arch/powerpc/kernel/msi.c
@@ -13,6 +13,16 @@

#include <asm/machdep.h>

+int arch_msi_set_iova(struct pci_dev *pdev, int region_num,
+ dma_addr_t iova, bool set)
+{
+ if (ppc_md.msi_set_iova) {
+ pr_debug("msi: Using platform get_region_count routine.\n");
+ return ppc_md.msi_set_iova(pdev, region_num, iova, set);
+ }
+ return 0;
+}
+
int arch_msi_get_region_count(void)
{
if (ppc_md.msi_get_region_count) {
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c
index eeebbf0..ad22d74 100644
--- a/arch/powerpc/sysdev/fsl_msi.c
+++ b/arch/powerpc/sysdev/fsl_msi.c
@@ -137,6 +137,46 @@ static int fsl_msi_get_region(int region_num, struct msi_region *region)
return -ENODEV;
}

+static int fsl_msi_set_iova(struct pci_dev *pdev, int region_num,
+ dma_addr_t iova, bool set)
+{
+ struct fsl_msi *msi_data;
+ struct fsl_msi_device *device;
+
+ list_for_each_entry(msi_data, &msi_head, list) {
+ if (msi_data->bank_index != region_num)
+ continue;
+ mutex_lock(&msi_data->lock);
+ if (set) {
+ list_for_each_entry(device, &msi_data->device_list, list) {
+ if (device->dev == pdev) {
+ device->iova = iova;
+ mutex_unlock(&msi_data->lock);
+ return 0;
+ }
+ }
+
+ device = kzalloc(sizeof(struct fsl_msi_device), GFP_KERNEL);
+ device->dev = pdev;
+ device->iova = iova;
+ list_add_tail(&device->list, &msi_data->device_list);
+ } else {
+ list_for_each_entry(device, &msi_data->device_list, list) {
+ if (device->dev == pdev) {
+ list_del(&device->list);
+ kfree(device);
+ mutex_unlock(&msi_data->lock);
+ return 0;
+ }
+ }
+ }
+
+ mutex_unlock(&msi_data->lock);
+ break;
+ }
+ return 0;
+}
+
static int fsl_msi_check_device(struct pci_dev *pdev, int nvec, int type)
{
if (type == PCI_CAP_ID_MSIX)
@@ -167,6 +207,7 @@ static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq,
struct msi_msg *msg,
struct fsl_msi *fsl_msi_data)
{
+ struct fsl_msi_device *device;
struct fsl_msi *msi_data = fsl_msi_data;
struct pci_controller *hose = pci_bus_to_host(pdev->bus);
u64 address; /* Physical address of the MSIIR */
@@ -181,6 +222,18 @@ static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq,
address = fsl_pci_immrbar_base(hose) +
(msi_data->msiir & 0xfffff);

+ printk("%s address = %llx\n", __func__, address);
+
+ mutex_lock(&msi_data->lock);
+ list_for_each_entry(device, &msi_data->device_list, list) {
+ if (device->dev == pdev) {
+ address = device->iova | (msi_data->msiir & 0xfff);
+ break;
+ }
+ }
+ mutex_unlock(&msi_data->lock);
+ printk("%s address = %llx\n", __func__, address);
+
msg->address_lo = lower_32_bits(address);
msg->address_hi = upper_32_bits(address);

@@ -356,6 +409,7 @@ static int fsl_of_msi_remove(struct platform_device *ofdev)
struct fsl_msi *msi = platform_get_drvdata(ofdev);
int virq, i;
struct fsl_msi_cascade_data *cascade_data;
+ struct fsl_msi_device *device;

if (msi->list.prev != NULL)
list_del(&msi->list);
@@ -371,6 +425,13 @@ static int fsl_of_msi_remove(struct platform_device *ofdev)
msi_bitmap_free(&msi->bitmap);
if ((msi->feature & FSL_PIC_IP_MASK) != FSL_PIC_IP_VMPIC)
iounmap(msi->msi_regs);
+
+ mutex_lock(&msi->lock);
+ list_for_each_entry(device, &msi->device_list, list) {
+ list_del(&device->list);
+ kfree(device);
+ }
+ mutex_unlock(&msi->lock);
kfree(msi);

return 0;
@@ -436,6 +497,8 @@ static int fsl_of_msi_probe(struct platform_device *dev)
dev_err(&dev->dev, "No memory for MSI structure\n");
return -ENOMEM;
}
+ INIT_LIST_HEAD(&msi->device_list);
+ mutex_init(&msi->lock);
platform_set_drvdata(dev, msi);

msi->irqhost = irq_domain_add_linear(dev->dev.of_node,
@@ -558,6 +621,7 @@ static int fsl_of_msi_probe(struct platform_device *dev)
ppc_md.msi_check_device = fsl_msi_check_device;
ppc_md.msi_get_region_count = fsl_msi_get_region_count;
ppc_md.msi_get_region = fsl_msi_get_region;
+ ppc_md.msi_set_iova = fsl_msi_set_iova;
} else if (ppc_md.setup_msi_irqs != fsl_setup_msi_irqs) {
dev_err(&dev->dev, "Different MSI driver already installed!\n");
err = -ENODEV;
diff --git a/arch/powerpc/sysdev/fsl_msi.h b/arch/powerpc/sysdev/fsl_msi.h
index a2cc5a2..adda5c3 100644
--- a/arch/powerpc/sysdev/fsl_msi.h
+++ b/arch/powerpc/sysdev/fsl_msi.h
@@ -27,9 +27,15 @@
#define FSL_PIC_IP_IPIC 0x00000002
#define FSL_PIC_IP_VMPIC 0x00000003

+struct fsl_msi_device {
+ struct list_head list;
+ struct pci_dev *dev;
+ dma_addr_t iova;
+};
+
struct fsl_msi {
struct irq_domain *irqhost;
-
+ struct mutex lock;
unsigned long cascade_irq;
phys_addr_t msiir; /* MSIIR Address in CCSR */
u32 ibs_shift; /* Shift of interrupt bit select */
@@ -37,7 +43,7 @@ struct fsl_msi {
void __iomem *msi_regs;
u32 feature;
int msi_virqs[NR_MSI_REG_MAX];
-
+ struct list_head device_list;
/*
* During probe each bank is assigned a index number.
* index number start from 0.
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 2643a29..59ec465 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -77,6 +77,18 @@ int __weak arch_msi_get_region(int region_num, struct msi_region *region)
return 0;
}

+int __weak arch_msi_set_iova(struct pci_dev *pdev, int region_num,
+ dma_addr_t iova, bool set)
+{
+ return 0;
+}
+
+int msi_set_iova(struct pci_dev *pdev, int region_num, dma_addr_t iova, bool set)
+{
+ return arch_msi_set_iova(pdev, region_num, iova, set);
+}
+EXPORT_SYMBOL(msi_set_iova);
+
int msi_get_region_count(void)
{
return arch_msi_get_region_count();
diff --git a/include/linux/pci.h b/include/linux/pci.h
index c587034..c6d3e58 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1195,6 +1195,12 @@ static inline int msi_get_region(int region_num, struct msi_region *region)
{
return 0;
}
+
+static inline int msi_set_iova(struct pci_dev *pdev, int region_num,
+ dma_addr_t iova, bool set)
+{
+ return 0;
+}
#else
int pci_enable_msi_block(struct pci_dev *dev, unsigned int nvec);
int pci_enable_msi_block_auto(struct pci_dev *dev, unsigned int *maxvec);
@@ -1209,6 +1215,8 @@ void pci_restore_msi_state(struct pci_dev *dev);
int pci_msi_enabled(void);
int msi_get_region_count(void);
int msi_get_region(int region_num, struct msi_region *region);
+int msi_set_iova(struct pci_dev *pdev, int region_num,
+ dma_addr_t iova, bool set);
#endif

#ifdef CONFIG_PCIEPORTBUS
--
1.7.0.4

2013-10-29 11:34:55

by Bharat Bhushan

[permalink] [raw]
Subject: [PATCH 0/5 RFC] vfio/pci: add interface to for MSI support with FSL PAMU

From: Bharat Bhushan <[email protected]>

PAMU (FSL IOMMU) has a concept of primary window and subwindows.
Primary window corresponds to the complete guest iova address space
(including MSI space), with respect to IOMMU_API this is termed as
geometry. IOVA Base of subwindow is determined from the number of
subwindows (configurable using iommu API).
MSI I/O page must be within the geometry and maximum supported
subwindows, so MSI IO-page is setup just after guest memory iova space.

So first four patches are for defining the interface to get:
- Number of MSI regions (which is number of MSI banks for powerpc)
- MSI-region address range: Physical page which have the
address/addresses used for generating MSI interrupt
and size of the page.

Last Patch is for setting up MSI iova-base for vfio devices assigned
in msi subsystem, so that when msi-message will be composed then this
configured iova will be used. Earlier we were using iommu interface
for getting the configured iova which was not currect and
Alex Williamson suggeested this type of interface.

Bharat Bhushan (5):
pci:msi: add weak function for returning msi region info
powerpc: pci: Add arch specific msi region interface
powerpc: msi: Extend the msi region interface to get info from
fsl_msi
pci: msi: expose msi region information functions
vfio: setup iova-base for msi interrupts for vfio assigned device

arch/powerpc/include/asm/machdep.h | 10 ++++
arch/powerpc/kernel/msi.c | 28 ++++++++++
arch/powerpc/sysdev/fsl_msi.c | 106 ++++++++++++++++++++++++++++++++++--
arch/powerpc/sysdev/fsl_msi.h | 19 ++++++-
drivers/pci/msi.c | 34 ++++++++++++
include/linux/msi.h | 14 +++++
include/linux/pci.h | 21 +++++++
7 files changed, 223 insertions(+), 9 deletions(-)

2013-10-29 11:35:36

by Bharat Bhushan

[permalink] [raw]
Subject: [PATCH 2/5 RFC] powerpc: pci: Add arch specific msi region interface

This patch adds the interface to get the msi region information from arch
specific code. The machine spicific code is not yet defined.

Signed-off-by: Bharat Bhushan <[email protected]>
---
arch/powerpc/include/asm/machdep.h | 8 ++++++++
arch/powerpc/kernel/msi.c | 18 ++++++++++++++++++
2 files changed, 26 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
index 8b48090..8d1b787 100644
--- a/arch/powerpc/include/asm/machdep.h
+++ b/arch/powerpc/include/asm/machdep.h
@@ -30,6 +30,7 @@ struct file;
struct pci_controller;
struct kimage;
struct pci_host_bridge;
+struct msi_region;

struct machdep_calls {
char *name;
@@ -124,6 +125,13 @@ struct machdep_calls {
int (*setup_msi_irqs)(struct pci_dev *dev,
int nvec, int type);
void (*teardown_msi_irqs)(struct pci_dev *dev);
+
+ /* Returns the number of MSI regions (banks) */
+ int (*msi_get_region_count)(void);
+
+ /* Returns the requested region's address and size */
+ int (*msi_get_region)(int region_num,
+ struct msi_region *region);
#endif

void (*restart)(char *cmd);
diff --git a/arch/powerpc/kernel/msi.c b/arch/powerpc/kernel/msi.c
index 8bbc12d..1a67787 100644
--- a/arch/powerpc/kernel/msi.c
+++ b/arch/powerpc/kernel/msi.c
@@ -13,6 +13,24 @@

#include <asm/machdep.h>

+int arch_msi_get_region_count(void)
+{
+ if (ppc_md.msi_get_region_count) {
+ pr_debug("msi: Using platform get_region_count routine.\n");
+ return ppc_md.msi_get_region_count();
+ }
+ return 0;
+}
+
+int arch_msi_get_region(int region_num, struct msi_region *region)
+{
+ if (ppc_md.msi_get_region) {
+ pr_debug("msi: Using platform get_region routine.\n");
+ return ppc_md.msi_get_region(region_num, region);
+ }
+ return 0;
+}
+
int arch_msi_check_device(struct pci_dev* dev, int nvec, int type)
{
if (!ppc_md.setup_msi_irqs || !ppc_md.teardown_msi_irqs) {
--
1.7.0.4