[PATCH v3 12/27] x86/MSI: Use MSI chip framework to configure MSI/MSI-X irq

2014-10-14 Thread Yijing Wang
Use MSI chip framework instead of arch MSI functions to configure
MSI/MSI-X irq. So we can manage MSI/MSI-X irq in a unified framework.

Signed-off-by: Yijing Wang 
---
 arch/x86/include/asm/pci.h |   13 +
 arch/x86/kernel/apic/io_apic.c |   19 +++
 arch/x86/pci/acpi.c|1 +
 arch/x86/pci/common.c  |3 +++
 4 files changed, 36 insertions(+), 0 deletions(-)

diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
index 0892ea0..f41b58a 100644
--- a/arch/x86/include/asm/pci.h
+++ b/arch/x86/include/asm/pci.h
@@ -20,6 +20,9 @@ struct pci_sysdata {
 #ifdef CONFIG_X86_64
void*iommu; /* IOMMU private data */
 #endif
+#ifdef CONFIG_PCI_MSI
+   struct msi_chip *msi_chip;
+#endif
 };
 
 extern int pci_routeirq;
@@ -41,6 +44,15 @@ static inline int pci_proc_domain(struct pci_bus *bus)
 }
 #endif
 
+#ifdef CONFIG_PCI_MSI
+static inline struct msi_chip *pci_msi_chip(struct pci_bus *bus)
+{
+   struct pci_sysdata *sd = bus->sysdata;
+
+   return sd->msi_chip;
+}
+#endif
+
 /* Can be used to override the logic in pci_scan_bus for skipping
already-configured bus numbers - to be used for buggy BIOSes
or architectures with incomplete PCI setup by the loader */
@@ -101,6 +113,7 @@ void native_teardown_msi_irq(unsigned int irq);
 void native_restore_msi_irqs(struct pci_dev *dev);
 int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc,
  unsigned int irq_base, unsigned int irq_offset);
+extern struct msi_chip *x86_msi_chip;
 #else
 #define native_setup_msi_irqs  NULL
 #define native_teardown_msi_irqNULL
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 29290f5..ec79b38 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -3227,11 +3227,30 @@ int native_setup_msi_irqs(struct pci_dev *dev, int 
nvec, int type)
return 0;
 }
 
+static int __native_setup_msi_irqs(struct msi_chip *chip,
+   struct pci_dev *dev, int nvec, int type)
+{
+   return native_setup_msi_irqs(dev, nvec, type);
+}
+
 void native_teardown_msi_irq(unsigned int irq)
 {
irq_free_hwirq(irq);
 }
 
+static void __native_teardown_msi_irq(struct msi_chip *chip,
+   unsigned int irq)
+{
+   native_teardown_msi_irq(irq);
+}
+
+static struct msi_chip native_msi_chip = {
+   .setup_irqs = __native_setup_msi_irqs,
+   .teardown_irq = __native_teardown_msi_irq,
+};
+
+struct msi_chip *x86_msi_chip = &native_msi_chip;
+
 #ifdef CONFIG_DMAR_TABLE
 static int
 dmar_msi_set_affinity(struct irq_data *data, const struct cpumask *mask,
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index cfd1b13..6341d6d 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -508,6 +508,7 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root 
*root)
 
sd = &info->sd;
sd->domain = domain;
+   sd->msi_chip = x86_msi_chip;
sd->node = node;
sd->companion = device;
 
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index 7b20bcc..0b2319a 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -468,6 +468,9 @@ void pcibios_scan_root(int busnum)
return;
}
sd->node = x86_pci_root_bus_node(busnum);
+#ifdef CONFIG_PCI_MSI
+   sd->msi_chip = x86_msi_chip;
+#endif
x86_pci_root_bus_resources(busnum, &resources);
printk(KERN_DEBUG "PCI: Probing PCI hardware (bus %02x)\n", busnum);
bus = pci_scan_root_bus(NULL, busnum, &pci_root_ops, sd, &resources);
-- 
1.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v3 03/27] s390/MSI: Use __msi_mask_irq() instead of default_msi_mask_irq()

2014-10-14 Thread Yijing Wang
Now only s390/MSI use default_msi_mask_irq() and
default_msix_mask_irq(), replace them with the common
msi mask irq functions __msi_mask_irq() and __msix_mask_irq().
Remove default_msi_mask_irq() and default_msix_mask_irq().

Signed-off-by: Yijing Wang 
---
 arch/s390/pci/pci.c |4 ++--
 include/linux/msi.h |2 --
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
index 2fa7b14..552b990 100644
--- a/arch/s390/pci/pci.c
+++ b/arch/s390/pci/pci.c
@@ -448,9 +448,9 @@ void arch_teardown_msi_irqs(struct pci_dev *pdev)
/* Release MSI interrupts */
list_for_each_entry(msi, &pdev->msi_list, list) {
if (msi->msi_attrib.is_msix)
-   default_msix_mask_irq(msi, 1);
+   __msix_mask_irq(msi, 1);
else
-   default_msi_mask_irq(msi, 1, 1);
+   __msi_mask_irq(msi, 1, 1);
irq_set_msi_desc(msi->irq, NULL);
irq_free_desc(msi->irq);
msi->msg.address_lo = 0;
diff --git a/include/linux/msi.h b/include/linux/msi.h
index 9ac1e3b..175aa21 100644
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -65,8 +65,6 @@ void arch_restore_msi_irqs(struct pci_dev *dev);
 
 void default_teardown_msi_irqs(struct pci_dev *dev);
 void default_restore_msi_irqs(struct pci_dev *dev);
-#define default_msi_mask_irq   __msi_mask_irq
-#define default_msix_mask_irq  __msix_mask_irq
 
 struct msi_chip {
struct module *owner;
-- 
1.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v3 25/27] Sparc/MSI: Use MSI chip framework to configure MSI/MSI-X irq

2014-10-14 Thread David Miller
From: Yijing Wang 
Date: Wed, 15 Oct 2014 11:07:13 +0800

> Use MSI chip framework instead of arch MSI functions to configure
> MSI/MSI-X irq. So we can manage MSI/MSI-X irq in a unified framework.
> 
> Signed-off-by: Yijing Wang 

Acked-by: David S. Miller 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v3 24/27] IA64/MSI: Use MSI chip framework to configure MSI/MSI-X irq

2014-10-14 Thread Yijing Wang
Use MSI chip framework instead of arch MSI functions to configure
MSI/MSI-X irq. So we can manage MSI/MSI-X irq in a unified framework.

Signed-off-by: Yijing Wang 
---
 arch/ia64/include/asm/pci.h |   10 ++
 arch/ia64/kernel/msi_ia64.c |   14 ++
 arch/ia64/pci/pci.c |1 +
 3 files changed, 21 insertions(+), 4 deletions(-)

diff --git a/arch/ia64/include/asm/pci.h b/arch/ia64/include/asm/pci.h
index 52af5ed..907dcba 100644
--- a/arch/ia64/include/asm/pci.h
+++ b/arch/ia64/include/asm/pci.h
@@ -94,6 +94,7 @@ struct pci_controller {
int segment;
int node;   /* nearest node with memory or NUMA_NO_NODE for 
global allocation */
 
+   struct msi_chip *msi_chip;
void *platform_data;
 };
 
@@ -101,6 +102,15 @@ struct pci_controller {
 #define PCI_CONTROLLER(busdev) ((struct pci_controller *) busdev->sysdata)
 #define pci_domain_nr(busdev)(PCI_CONTROLLER(busdev)->segment)
 
+extern struct msi_chip chip;
+
+static inline struct msi_chip *pci_msi_chip(struct pci_bus *bus)
+{
+   struct pci_controller *ctrl = bus->sysdata;
+
+   return ctrl->msi_chip;
+}
+
 extern struct pci_ops pci_root_ops;
 
 static inline int pci_proc_domain(struct pci_bus *bus)
diff --git a/arch/ia64/kernel/msi_ia64.c b/arch/ia64/kernel/msi_ia64.c
index 8c3730c..401fc98 100644
--- a/arch/ia64/kernel/msi_ia64.c
+++ b/arch/ia64/kernel/msi_ia64.c
@@ -112,15 +112,16 @@ static struct irq_chip ia64_msi_chip = {
 };
 
 
-int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
+static int arch_ia64_setup_msi_irq(struct msi_chip *chip,
+   struct pci_dev *dev, struct msi_desc *desc)
 {
if (platform_setup_msi_irq)
-   return platform_setup_msi_irq(pdev, desc);
+   return platform_setup_msi_irq(dev, desc);
 
-   return ia64_setup_msi_irq(pdev, desc);
+   return ia64_setup_msi_irq(dev, desc);
 }
 
-void arch_teardown_msi_irq(unsigned int irq)
+static void arch_ia64_teardown_msi_irq(struct msi_chip *chip, unsigned int irq)
 {
if (platform_teardown_msi_irq)
return platform_teardown_msi_irq(irq);
@@ -128,6 +129,11 @@ void arch_teardown_msi_irq(unsigned int irq)
return ia64_teardown_msi_irq(irq);
 }
 
+struct msi_chip chip = {
+   .setup_irq = arch_ia64_setup_msi_irq,
+   .teardown_irq = arch_ia64_teardown_msi_irq,
+};
+
 #ifdef CONFIG_INTEL_IOMMU
 #ifdef CONFIG_SMP
 static int dmar_msi_set_affinity(struct irq_data *data,
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index 291a582..299b67d 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -437,6 +437,7 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root 
*root)
 
controller->companion = device;
controller->node = acpi_get_node(device->handle);
+   controller->msi_chip = &chip;
 
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info) {
-- 
1.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v3 20/27] MIPS/Xlr/MSI: Use MSI chip framework to configure MSI/MSI-X irq

2014-10-14 Thread Yijing Wang
Use MSI chip framework instead of arch MSI functions to configure
MSI/MSI-X irq. So we can manage MSI/MSI-X irq in a unified framework.

Signed-off-by: Yijing Wang 
---
 arch/mips/pci/pci-xlr.c |   17 +++--
 1 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/arch/mips/pci/pci-xlr.c b/arch/mips/pci/pci-xlr.c
index 0dde803..0e611de 100644
--- a/arch/mips/pci/pci-xlr.c
+++ b/arch/mips/pci/pci-xlr.c
@@ -149,6 +149,8 @@ static struct resource nlm_pci_io_resource = {
.flags  = IORESOURCE_IO,
 };
 
+static struct msi_chip xlr_msi_chip;
+
 struct pci_controller nlm_pci_controller = {
.index  = 0,
.pci_ops= &nlm_pci_ops,
@@ -156,6 +158,9 @@ struct pci_controller nlm_pci_controller = {
.mem_offset = 0xUL,
.io_resource= &nlm_pci_io_resource,
.io_offset  = 0xUL,
+#ifdef CONFIG_PCI_MSI
+   .msi_chip = &xlr_msi_chip,
+#endif
 };
 
 /*
@@ -214,11 +219,13 @@ static int get_irq_vector(const struct pci_dev *dev)
 }
 
 #ifdef CONFIG_PCI_MSI
-void arch_teardown_msi_irq(unsigned int irq)
+static void xlr_teardown_msi_irq(struct msi_chip *chip,
+   unsigned int irq)
 {
 }
 
-int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
+static int xlr_setup_msi_irq(struct msi_chip *chip,
+   struct pci_dev *dev, struct msi_desc *desc)
 {
struct msi_msg msg;
struct pci_dev *lnk;
@@ -263,6 +270,12 @@ int arch_setup_msi_irq(struct pci_dev *dev, struct 
msi_desc *desc)
write_msi_msg(irq, &msg);
return 0;
 }
+
+static struct msi_chip xlr_msi_chip = {
+   .setup_irq = xlr_setup_msi_irq,
+   .teardown_irq = xlr_teardown_msi_irq,
+};
+
 #endif
 
 /* Extra ACK needed for XLR on chip PCI controller */
-- 
1.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v3 27/27] PCI/MSI: Clean up unused MSI arch functions

2014-10-14 Thread Yijing Wang
Now we use struct msi_chip in all platforms to configure
MSI/MSI-X. We can clean up the unused arch functions.

Signed-off-by: Yijing Wang 
---
Hi Lucas,
   I dropped the reviewed-by, because this version has a lot changes
compared to last one, I guess you may want to check it again.
---
 drivers/iommu/irq_remapping.c |2 +-
 drivers/pci/msi.c |  103 +++--
 include/linux/msi.h   |   14 --
 include/linux/pci.h   |8 ---
 4 files changed, 39 insertions(+), 88 deletions(-)

diff --git a/drivers/iommu/irq_remapping.c b/drivers/iommu/irq_remapping.c
index 48d57e9..77160a5 100644
--- a/drivers/iommu/irq_remapping.c
+++ b/drivers/iommu/irq_remapping.c
@@ -92,7 +92,7 @@ error:
 
/*
 * Restore altered MSI descriptor fields and prevent just destroyed
-* IRQs from tearing down again in default_teardown_msi_irqs()
+* IRQs from tearing down again in teardown_msi_irqs()
 */
msidesc->irq = 0;
msidesc->nvec_used = 0;
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 5cbd774..b9fefe9 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -28,54 +28,31 @@ int pci_msi_ignore_mask;
 #define msix_table_size(flags) ((flags & PCI_MSIX_FLAGS_QSIZE) + 1)
 
 
-/* Arch hooks */
-
-int __weak arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
-{
-   struct msi_chip *chip;
-   int err;
-
-   chip = pci_msi_chip(dev->bus);
-   if (!chip || !chip->setup_irq)
-   return -EINVAL;
-
-   err = chip->setup_irq(chip, dev, desc);
-   if (err < 0)
-   return err;
-
-   return 0;
-}
-
-void __weak arch_teardown_msi_irq(unsigned int irq)
-{
-   struct msi_desc *entry = irq_get_msi_desc(irq);
-   struct msi_chip *chip = pci_msi_chip(entry->dev->bus);
-
-   if (!chip || !chip->teardown_irq)
-   return;
-
-   chip->teardown_irq(chip, irq);
-}
-
-int __weak arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+int setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 {
struct msi_desc *entry;
int ret;
struct msi_chip *chip;
 
chip = pci_msi_chip(dev->bus);
-   if (chip && chip->setup_irqs)
+   if (!chip)
+  return -EINVAL;
+
+   if (chip->setup_irqs)
return chip->setup_irqs(chip, dev, nvec, type);
 
/*
 * If an architecture wants to support multiple MSI, it needs to
-* override arch_setup_msi_irqs()
+* implement chip->setup_irqs().
 */
if (type == PCI_CAP_ID_MSI && nvec > 1)
return 1;
 
+   if (!chip->setup_irq)
+   return -EINVAL;
+
list_for_each_entry(entry, &dev->msi_list, list) {
-   ret = arch_setup_msi_irq(dev, entry);
+   ret = chip->setup_irq(chip, dev, entry);
if (ret < 0)
return ret;
if (ret > 0)
@@ -85,13 +62,20 @@ int __weak arch_setup_msi_irqs(struct pci_dev *dev, int 
nvec, int type)
return 0;
 }
 
-/*
- * We have a default implementation available as a separate non-weak
- * function, as it is used by the Xen x86 PCI code
- */
-void default_teardown_msi_irqs(struct pci_dev *dev)
+static void teardown_msi_irqs(struct pci_dev *dev)
 {
struct msi_desc *entry;
+   struct msi_chip *chip;
+
+   chip = pci_msi_chip(dev->bus);
+   if (!chip)
+   return;
+
+   if (chip->teardown_irqs)
+   return chip->teardown_irqs(chip, dev);
+
+   if (!chip->teardown_irq)
+   return;
 
list_for_each_entry(entry, &dev->msi_list, list) {
int i, nvec;
@@ -102,20 +86,10 @@ void default_teardown_msi_irqs(struct pci_dev *dev)
else
nvec = 1 << entry->msi_attrib.multiple;
for (i = 0; i < nvec; i++)
-   arch_teardown_msi_irq(entry->irq + i);
+   chip->teardown_irq(chip, entry->irq + i);
}
 }
 
-void __weak arch_teardown_msi_irqs(struct pci_dev *dev)
-{
-   struct msi_chip *chip = pci_msi_chip(dev->bus);
-
-   if (chip && chip->teardown_irqs)
-   return chip->teardown_irqs(chip, dev);
-
-   return default_teardown_msi_irqs(dev);
-}
-
 static void default_restore_msi_irq(struct pci_dev *dev, int irq)
 {
struct msi_desc *entry;
@@ -134,10 +108,18 @@ static void default_restore_msi_irq(struct pci_dev *dev, 
int irq)
__write_msi_msg(entry, &entry->msg);
 }
 
-void __weak arch_restore_msi_irqs(struct pci_dev *dev)
+static void default_restore_msi_irqs(struct pci_dev *dev)
 {
-   struct msi_chip *chip = pci_msi_chip(dev->bus);
+   struct msi_desc *entry = NULL;
+
+   list_for_each_entry(entry, &dev->msi_list, list) {
+   default_restore_msi_irq(dev, entry->irq);
+   }
+}
 
+static void restore_msi_irqs(struct pci_dev *dev)
+{
+   s

[PATCH v3 23/27] arm/iop13xx/MSI: Use MSI chip framework to configure MSI/MSI-X irq

2014-10-14 Thread Yijing Wang
Use MSI chip framework instead of arch MSI functions to configure
MSI/MSI-X irq. So we can manage MSI/MSI-X irq in a unified framework.

Signed-off-by: Yijing Wang 
---
 arch/arm/mach-iop13xx/include/mach/pci.h |4 
 arch/arm/mach-iop13xx/iq81340mc.c|3 +++
 arch/arm/mach-iop13xx/iq81340sc.c|5 -
 arch/arm/mach-iop13xx/msi.c  |   11 +--
 4 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-iop13xx/include/mach/pci.h 
b/arch/arm/mach-iop13xx/include/mach/pci.h
index 59f42b5..c87ac3a 100644
--- a/arch/arm/mach-iop13xx/include/mach/pci.h
+++ b/arch/arm/mach-iop13xx/include/mach/pci.h
@@ -11,6 +11,10 @@ void iop13xx_atu_select(struct hw_pci *plat_pci);
 void iop13xx_pci_init(void);
 void iop13xx_map_pci_memory(void);
 
+#ifdef CONFIG_PCI_MSI
+extern struct msi_chip iop13xx_msi_chip;
+#endif
+
 #define IOP_PCI_STATUS_ERROR (PCI_STATUS_PARITY |   \
   PCI_STATUS_SIG_TARGET_ABORT | \
   PCI_STATUS_REC_TARGET_ABORT | \
diff --git a/arch/arm/mach-iop13xx/iq81340mc.c 
b/arch/arm/mach-iop13xx/iq81340mc.c
index 9cd07d3..1f499b6 100644
--- a/arch/arm/mach-iop13xx/iq81340mc.c
+++ b/arch/arm/mach-iop13xx/iq81340mc.c
@@ -59,6 +59,9 @@ static struct hw_pci iq81340mc_pci __initdata = {
.map_irq= iq81340mc_pcix_map_irq,
.scan   = iop13xx_scan_bus,
.preinit= iop13xx_pci_init,
+#ifdef CONFIG_PCI_MSI
+   .msi_chip   = &iop13xx_msi_chip,
+#endif
 };
 
 static int __init iq81340mc_pci_init(void)
diff --git a/arch/arm/mach-iop13xx/iq81340sc.c 
b/arch/arm/mach-iop13xx/iq81340sc.c
index b3ec11c..8bdfdc5 100644
--- a/arch/arm/mach-iop13xx/iq81340sc.c
+++ b/arch/arm/mach-iop13xx/iq81340sc.c
@@ -60,7 +60,10 @@ static struct hw_pci iq81340sc_pci __initdata = {
.setup  = iop13xx_pci_setup,
.scan   = iop13xx_scan_bus,
.map_irq= iq81340sc_atux_map_irq,
-   .preinit= iop13xx_pci_init
+   .preinit= iop13xx_pci_init,
+#ifdef CONFIG_PCI_MSI
+   .msi_chip   = &iop13xx_msi_chip,
+#endif
 };
 
 static int __init iq81340sc_pci_init(void)
diff --git a/arch/arm/mach-iop13xx/msi.c b/arch/arm/mach-iop13xx/msi.c
index e7730cf..3135a63 100644
--- a/arch/arm/mach-iop13xx/msi.c
+++ b/arch/arm/mach-iop13xx/msi.c
@@ -132,7 +132,8 @@ static struct irq_chip iop13xx_msi_chip = {
.irq_unmask = unmask_msi_irq,
 };
 
-int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
+static int iop13xx_setup_msi_irq(struct msi_chip *chip,
+   struct pci_dev *dev, struct msi_desc *desc)
 {
int id, irq = irq_alloc_desc_from(IRQ_IOP13XX_MSI_0, -1);
struct msi_msg msg;
@@ -159,7 +160,13 @@ int arch_setup_msi_irq(struct pci_dev *pdev, struct 
msi_desc *desc)
return 0;
 }
 
-void arch_teardown_msi_irq(unsigned int irq)
+static void iop13xx_teardown_msi_irq(struct msi_chip *chip,
+   unsigned int irq)
 {
irq_free_desc(irq);
 }
+
+struct msi_chip iop13xx_chip = {
+   .setup_irq = iop13xx_setup_msi_irq,
+   .teardown_irq = iop13xx_teardown_msi_irq,
+};
-- 
1.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v3 04/27] arm/MSI: Save MSI chip in pci_sys_data

2014-10-14 Thread Yijing Wang
Saving msi chip in pci_sys_data can make pci bus and
devices don't need to know msi chip detail, it also
make pci enumeration code be decoupled from msi chip.
In fact, all pci devices under the same pci hostbridge
share same msi chip. So msi chip should be seen as one
of resources or attributes to be initialized in pci host
bridge driver. Currently, pci hostbridge drivers create
pci_host_bridge in pci_create_root_bus(), and pass arch
specific pci sysdata to core pci scan functions. So pci
arch sysdata is good place to save msi chip.

Signed-off-by: Yijing Wang 
---
 arch/arm/include/asm/mach/pci.h |6 ++
 arch/arm/include/asm/pci.h  |9 +
 arch/arm/kernel/bios32.c|3 +++
 drivers/pci/msi.c   |6 ++
 include/linux/pci.h |9 +
 5 files changed, 33 insertions(+), 0 deletions(-)

diff --git a/arch/arm/include/asm/mach/pci.h b/arch/arm/include/asm/mach/pci.h
index 7fc4278..59b0d87 100644
--- a/arch/arm/include/asm/mach/pci.h
+++ b/arch/arm/include/asm/mach/pci.h
@@ -22,6 +22,9 @@ struct hw_pci {
 #ifdef CONFIG_PCI_DOMAINS
int domain;
 #endif
+#ifdef CONFIG_PCI_MSI
+   struct msi_chip *msi_chip;
+#endif
struct pci_ops  *ops;
int nr_controllers;
void**private_data;
@@ -47,6 +50,9 @@ struct pci_sys_data {
 #ifdef CONFIG_PCI_DOMAINS
int domain;
 #endif
+#ifdef CONFIG_PCI_MSI
+   struct msi_chip *msi_chip;
+#endif
struct list_head node;
int busnr;  /* primary bus number   
*/
u64 mem_offset; /* bus->cpu memory mapping offset   
*/
diff --git a/arch/arm/include/asm/pci.h b/arch/arm/include/asm/pci.h
index 7e95d85..b562c09 100644
--- a/arch/arm/include/asm/pci.h
+++ b/arch/arm/include/asm/pci.h
@@ -31,6 +31,15 @@ static inline int pci_proc_domain(struct pci_bus *bus)
 }
 #endif /* CONFIG_PCI_DOMAINS */
 
+#ifdef CONFIG_PCI_MSI
+static inline struct msi_chip *pci_msi_chip(struct pci_bus *bus)
+{
+   struct pci_sys_data *root = bus->sysdata;
+
+   return root->msi_chip;
+}
+#endif
+
 /*
  * The PCI address space does equal the physical memory address space.
  * The networking and block device layers use this boolean for bounce
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index 17a26c1..a19038d 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -471,6 +471,9 @@ static void pcibios_init_hw(struct device *parent, struct 
hw_pci *hw,
 #ifdef CONFIG_PCI_DOMAINS
sys->domain  = hw->domain;
 #endif
+#ifdef CONFIG_PCI_MSI
+   sys->msi_chip = hw->msi_chip;
+#endif
sys->busnr   = busnr;
sys->swizzle = hw->swizzle;
sys->map_irq = hw->map_irq;
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 22e413c..f11108c 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -35,6 +35,9 @@ int __weak arch_setup_msi_irq(struct pci_dev *dev, struct 
msi_desc *desc)
struct msi_chip *chip = dev->bus->msi;
int err;
 
+   if (!chip)
+   chip = pci_msi_chip(dev->bus);
+
if (!chip || !chip->setup_irq)
return -EINVAL;
 
@@ -50,6 +53,9 @@ void __weak arch_teardown_msi_irq(unsigned int irq)
struct msi_desc *entry = irq_get_msi_desc(irq);
struct msi_chip *chip = entry->dev->bus->msi;
 
+   if (!chip)
+   chip = pci_msi_chip(entry->dev->bus);
+
if (!chip || !chip->teardown_irq)
return;
 
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 9cd2721..7a48b40 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1433,6 +1433,15 @@ static inline int pci_get_new_domain_nr(void) { return 
-ENOSYS; }
 
 #include 
 
+/* Just avoid compile error, will be clean up later */
+#ifdef CONFIG_PCI_MSI
+
+#ifndef pci_msi_chip
+#define pci_msi_chip(bus)  NULL
+#endif
+
+#endif
+
 /* these helpers provide future and backwards compatibility
  * for accessing popular PCI BAR info */
 #define pci_resource_start(dev, bar)   ((dev)->resource[(bar)].start)
-- 
1.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v3 05/27] PCI: tegra: Save msi chip in pci_sys_data

2014-10-14 Thread Yijing Wang
Save msi chip in pci_sys_data instead of assign
msi chip to every pci bus in .add_bus().

Signed-off-by: Yijing Wang 
---
 drivers/pci/host/pci-tegra.c |   13 +++--
 1 files changed, 3 insertions(+), 10 deletions(-)

diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c
index 3d43874..5af0525 100644
--- a/drivers/pci/host/pci-tegra.c
+++ b/drivers/pci/host/pci-tegra.c
@@ -694,15 +694,6 @@ static int tegra_pcie_map_irq(const struct pci_dev *pdev, 
u8 slot, u8 pin)
return irq;
 }
 
-static void tegra_pcie_add_bus(struct pci_bus *bus)
-{
-   if (IS_ENABLED(CONFIG_PCI_MSI)) {
-   struct tegra_pcie *pcie = sys_to_pcie(bus->sysdata);
-
-   bus->msi = &pcie->msi.chip;
-   }
-}
-
 static struct pci_bus *tegra_pcie_scan_bus(int nr, struct pci_sys_data *sys)
 {
struct tegra_pcie *pcie = sys_to_pcie(sys);
@@ -1881,11 +1872,13 @@ static int tegra_pcie_enable(struct tegra_pcie *pcie)
 
memset(&hw, 0, sizeof(hw));
 
+#ifdef CONFIG_PCI_MSI
+   hw.msi_chip = &pcie->msi.chip;
+#endif
hw.nr_controllers = 1;
hw.private_data = (void **)&pcie;
hw.setup = tegra_pcie_setup;
hw.map_irq = tegra_pcie_map_irq;
-   hw.add_bus = tegra_pcie_add_bus;
hw.scan = tegra_pcie_scan_bus;
hw.ops = &tegra_pcie_ops;
 
-- 
1.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v3 22/27] s390/MSI: Use MSI chip framework to configure MSI/MSI-X irq

2014-10-14 Thread Yijing Wang
Use MSI chip framework instead of arch MSI functions to configure
MSI/MSI-X irq. So we can manage MSI/MSI-X irq in a unified framework.

Signed-off-by: Yijing Wang 
---
Hi Sebastian,
   I dropped the Acked-by , because this version has a
lot changes compared to last. So, I guess you may want to check it again.
---
 arch/s390/include/asm/pci.h |9 +
 arch/s390/pci/pci.c |   12 ++--
 2 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h
index c030900..4d41f08 100644
--- a/arch/s390/include/asm/pci.h
+++ b/arch/s390/include/asm/pci.h
@@ -88,6 +88,8 @@ struct zpci_dev {
u32 uid;/* user defined id */
u8 util_str[CLP_UTIL_STR_LEN];  /* utility string */
 
+   struct msi_chip *msi_chip;
+
/* IRQ stuff */
u64 msi_addr;   /* MSI address */
struct airq_iv *aibv;   /* adapter interrupt bit vector */
@@ -121,6 +123,13 @@ struct zpci_dev {
struct dentry   *debugfs_perf;
 };
 
+static inline struct msi_chip *pci_msi_chip(struct pci_bus *bus)
+{
+   struct zpci_dev *zpci = bus->sysdata;
+
+   return zpci->msi_chip;
+}
+
 static inline bool zdev_enabled(struct zpci_dev *zdev)
 {
return (zdev->fh & (1UL << 31)) ? true : false;
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
index 552b990..bf6732f 100644
--- a/arch/s390/pci/pci.c
+++ b/arch/s390/pci/pci.c
@@ -358,7 +358,8 @@ static void zpci_irq_handler(struct airq_struct *airq)
}
 }
 
-int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
+static int zpci_setup_msi_irqs(struct msi_chip *chip,
+   struct pci_dev *pdev, int nvec, int type)
 {
struct zpci_dev *zdev = get_zdev(pdev);
unsigned int hwirq, msi_vecs;
@@ -434,7 +435,8 @@ out:
return rc;
 }
 
-void arch_teardown_msi_irqs(struct pci_dev *pdev)
+static void zpci_teardown_msi_irqs(struct msi_chip *chip,
+   struct pci_dev *pdev)
 {
struct zpci_dev *zdev = get_zdev(pdev);
struct msi_desc *msi;
@@ -464,6 +466,11 @@ void arch_teardown_msi_irqs(struct pci_dev *pdev)
airq_iv_free_bit(zpci_aisb_iv, zdev->aisb);
 }
 
+static struct msi_chip zpci_msi_chip = {
+   .setup_irqs = zpci_setup_msi_irqs,
+   .teardown_irqs = zpci_teardown_msi_irqs,
+};
+
 static void zpci_map_resources(struct zpci_dev *zdev)
 {
struct pci_dev *pdev = zdev->pdev;
@@ -749,6 +756,7 @@ static int zpci_scan_bus(struct zpci_dev *zdev)
if (ret)
return ret;
 
+   zdev->msi_chip = &zpci_msi_chip;
zdev->bus = pci_scan_root_bus(NULL, ZPCI_BUS_NR, &pci_root_ops,
  zdev, &resources);
if (!zdev->bus) {
-- 
1.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v3 19/27] MIPS/Xlp/MSI: Use MSI chip framework to configure MSI/MSI-X irq

2014-10-14 Thread Yijing Wang
Use MSI chip framework instead of arch MSI functions to configure
MSI/MSI-X IRQ. So we can manage MSI/MSI-X irq in a unified framework.

Signed-off-by: Yijing Wang 
---
 arch/mips/include/asm/netlogic/xlp-hal/pcibus.h |1 +
 arch/mips/pci/msi-xlp.c |   11 +--
 arch/mips/pci/pci-xlp.c |3 +++
 3 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/arch/mips/include/asm/netlogic/xlp-hal/pcibus.h 
b/arch/mips/include/asm/netlogic/xlp-hal/pcibus.h
index 91540f4..90646ad 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/pcibus.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/pcibus.h
@@ -103,6 +103,7 @@
 
 #ifdef CONFIG_PCI_MSI
 void xlp_init_node_msi_irqs(int node, int link);
+extern struct msi_chip xlp_chip;
 #else
 static inline void xlp_init_node_msi_irqs(int node, int link) {}
 #endif
diff --git a/arch/mips/pci/msi-xlp.c b/arch/mips/pci/msi-xlp.c
index e469dc7..cca2257 100644
--- a/arch/mips/pci/msi-xlp.c
+++ b/arch/mips/pci/msi-xlp.c
@@ -245,7 +245,8 @@ static struct irq_chip xlp_msix_chip = {
.irq_unmask = unmask_msi_irq,
 };
 
-void arch_teardown_msi_irq(unsigned int irq)
+static void xlp_teardown_msi_irq(struct msi_chip *chip,
+   unsigned int irq)
 {
 }
 
@@ -450,7 +451,8 @@ static int xlp_setup_msix(uint64_t lnkbase, int node, int 
link,
return 0;
 }
 
-int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
+static int xlp_setup_msi_irq(struct msi_chip *chip,
+   struct pci_dev *dev, struct msi_desc *desc)
 {
struct pci_dev *lnkdev;
uint64_t lnkbase;
@@ -472,6 +474,11 @@ int arch_setup_msi_irq(struct pci_dev *dev, struct 
msi_desc *desc)
return xlp_setup_msi(lnkbase, node, link, desc);
 }
 
+struct msi_chip xlp_chip = {
+   .setup_irq = xlp_setup_msi_irq,
+   .teardown_irq = xlp_teardown_msi_irq,
+};
+
 void __init xlp_init_node_msi_irqs(int node, int link)
 {
struct nlm_soc_info *nodep;
diff --git a/arch/mips/pci/pci-xlp.c b/arch/mips/pci/pci-xlp.c
index 7babf01..5d7b6a0 100644
--- a/arch/mips/pci/pci-xlp.c
+++ b/arch/mips/pci/pci-xlp.c
@@ -174,6 +174,9 @@ struct pci_controller nlm_pci_controller = {
.mem_offset = 0xUL,
.io_resource= &nlm_pci_io_resource,
.io_offset  = 0xUL,
+#ifdef CONFIG_PCI_MSI
+   .msi_chip = &xlp_chip,
+#endif
 };
 
 struct pci_dev *xlp_get_pcie_link(const struct pci_dev *dev)
-- 
1.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v3 09/27] arm/PCI: Clean unused pcibios_add_bus() and pcibios_remove_bus()

2014-10-14 Thread Yijing Wang
MSI chip will be saved in pci_sys_data, now we can
clean up pcibios_add_bus() and pcibios_remove_bus()
in arm, and use pci_find_msi_chip() to get msi chip
in core MSI code.

Signed-off-by: Yijing Wang 
---
 arch/arm/include/asm/mach/pci.h |4 
 arch/arm/kernel/bios32.c|   16 
 drivers/pci/msi.c   |   11 +++
 3 files changed, 3 insertions(+), 28 deletions(-)

diff --git a/arch/arm/include/asm/mach/pci.h b/arch/arm/include/asm/mach/pci.h
index 59b0d87..230b2c9 100644
--- a/arch/arm/include/asm/mach/pci.h
+++ b/arch/arm/include/asm/mach/pci.h
@@ -39,8 +39,6 @@ struct hw_pci {
  resource_size_t start,
  resource_size_t size,
  resource_size_t align);
-   void(*add_bus)(struct pci_bus *bus);
-   void(*remove_bus)(struct pci_bus *bus);
 };
 
 /*
@@ -71,8 +69,6 @@ struct pci_sys_data {
  resource_size_t start,
  resource_size_t size,
  resource_size_t align);
-   void(*add_bus)(struct pci_bus *bus);
-   void(*remove_bus)(struct pci_bus *bus);
void*private_data;  /* platform controller private data 
*/
 };
 
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index a19038d..b1b872e 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -360,20 +360,6 @@ void pcibios_fixup_bus(struct pci_bus *bus)
 }
 EXPORT_SYMBOL(pcibios_fixup_bus);
 
-void pcibios_add_bus(struct pci_bus *bus)
-{
-   struct pci_sys_data *sys = bus->sysdata;
-   if (sys->add_bus)
-   sys->add_bus(bus);
-}
-
-void pcibios_remove_bus(struct pci_bus *bus)
-{
-   struct pci_sys_data *sys = bus->sysdata;
-   if (sys->remove_bus)
-   sys->remove_bus(bus);
-}
-
 /*
  * Swizzle the device pin each time we cross a bridge.  If a platform does
  * not provide a swizzle function, we perform the standard PCI swizzling.
@@ -478,8 +464,6 @@ static void pcibios_init_hw(struct device *parent, struct 
hw_pci *hw,
sys->swizzle = hw->swizzle;
sys->map_irq = hw->map_irq;
sys->align_resource = hw->align_resource;
-   sys->add_bus = hw->add_bus;
-   sys->remove_bus = hw->remove_bus;
INIT_LIST_HEAD(&sys->resources);
 
if (hw->private_data)
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index f11108c..56e54ad 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -32,12 +32,10 @@ int pci_msi_ignore_mask;
 
 int __weak arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
 {
-   struct msi_chip *chip = dev->bus->msi;
+   struct msi_chip *chip;
int err;
 
-   if (!chip)
-   chip = pci_msi_chip(dev->bus);
-
+   chip = pci_msi_chip(dev->bus);
if (!chip || !chip->setup_irq)
return -EINVAL;
 
@@ -51,10 +49,7 @@ int __weak arch_setup_msi_irq(struct pci_dev *dev, struct 
msi_desc *desc)
 void __weak arch_teardown_msi_irq(unsigned int irq)
 {
struct msi_desc *entry = irq_get_msi_desc(irq);
-   struct msi_chip *chip = entry->dev->bus->msi;
-
-   if (!chip)
-   chip = pci_msi_chip(entry->dev->bus);
+   struct msi_chip *chip = pci_msi_chip(entry->dev->bus);
 
if (!chip || !chip->teardown_irq)
return;
-- 
1.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v3 11/27] PCI/MSI: Refactor struct msi_chip to make it become more common

2014-10-14 Thread Yijing Wang
Now there are a lot of __weak arch functions in MSI code.
These functions make MSI driver complex. Thierry introduced
MSI chip framework to configure MSI/MSI-X irq in arm. Use
MSI chip framework to refactor all other platform MSI
code to eliminate weak arch MSI functions. This patch add
.restore_irqs(), .teardown_irqs() and .setup_irqs() to make it
become more common.

Signed-off-by: Yijing Wang 
Reviewed-by: Lucas Stach 
---
 drivers/pci/msi.c   |   15 +++
 include/linux/msi.h |4 
 2 files changed, 19 insertions(+), 0 deletions(-)

diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 56e54ad..5cbd774 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -61,6 +61,11 @@ int __weak arch_setup_msi_irqs(struct pci_dev *dev, int 
nvec, int type)
 {
struct msi_desc *entry;
int ret;
+   struct msi_chip *chip;
+
+   chip = pci_msi_chip(dev->bus);
+   if (chip && chip->setup_irqs)
+   return chip->setup_irqs(chip, dev, nvec, type);
 
/*
 * If an architecture wants to support multiple MSI, it needs to
@@ -103,6 +108,11 @@ void default_teardown_msi_irqs(struct pci_dev *dev)
 
 void __weak arch_teardown_msi_irqs(struct pci_dev *dev)
 {
+   struct msi_chip *chip = pci_msi_chip(dev->bus);
+
+   if (chip && chip->teardown_irqs)
+   return chip->teardown_irqs(chip, dev);
+
return default_teardown_msi_irqs(dev);
 }
 
@@ -126,6 +136,11 @@ static void default_restore_msi_irq(struct pci_dev *dev, 
int irq)
 
 void __weak arch_restore_msi_irqs(struct pci_dev *dev)
 {
+   struct msi_chip *chip = pci_msi_chip(dev->bus);
+
+   if (chip && chip->restore_irqs)
+ return chip->restore_irqs(chip, dev);
+
return default_restore_msi_irqs(dev);
 }
 
diff --git a/include/linux/msi.h b/include/linux/msi.h
index 175aa21..eb5ae36 100644
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -74,7 +74,11 @@ struct msi_chip {
 
int (*setup_irq)(struct msi_chip *chip, struct pci_dev *dev,
 struct msi_desc *desc);
+   int (*setup_irqs)(struct msi_chip *chip, struct pci_dev *dev,
+   int nvec, int type);
void (*teardown_irq)(struct msi_chip *chip, unsigned int irq);
+   void (*teardown_irqs)(struct msi_chip *chip, struct pci_dev *dev);
+   void (*restore_irqs)(struct msi_chip *chip, struct pci_dev *dev);
 };
 
 #endif /* LINUX_MSI_H */
-- 
1.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v3 08/27] PCI: mvebu: Save msi chip in pci_sys_data

2014-10-14 Thread Yijing Wang
Save msi chip in pci_sys_data instead of assign
msi chip to every pci bus in .add_bus().

Signed-off-by: Yijing Wang 
---
 drivers/pci/host/pci-mvebu.c |   10 +++---
 1 files changed, 3 insertions(+), 7 deletions(-)

diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c
index b1315e1..f8e9c6c 100644
--- a/drivers/pci/host/pci-mvebu.c
+++ b/drivers/pci/host/pci-mvebu.c
@@ -774,12 +774,6 @@ static struct pci_bus *mvebu_pcie_scan_bus(int nr, struct 
pci_sys_data *sys)
return bus;
 }
 
-static void mvebu_pcie_add_bus(struct pci_bus *bus)
-{
-   struct mvebu_pcie *pcie = sys_to_pcie(bus->sysdata);
-   bus->msi = pcie->msi;
-}
-
 static resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev,
 const struct resource *res,
 resource_size_t start,
@@ -816,6 +810,9 @@ static void mvebu_pcie_enable(struct mvebu_pcie *pcie)
 
memset(&hw, 0, sizeof(hw));
 
+#ifdef CONFIG_PCI_MSI
+   hw.msi_chip = pcie->msi;
+#endif
hw.nr_controllers = 1;
hw.private_data   = (void **)&pcie;
hw.setup  = mvebu_pcie_setup;
@@ -823,7 +820,6 @@ static void mvebu_pcie_enable(struct mvebu_pcie *pcie)
hw.map_irq= of_irq_parse_and_map_pci;
hw.ops= &mvebu_pcie_ops;
hw.align_resource = mvebu_pcie_align_resource;
-   hw.add_bus= mvebu_pcie_add_bus;
 
pci_common_init(&hw);
 }
-- 
1.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v3 10/27] PCI/MSI: Remove useless bus->msi assignment

2014-10-14 Thread Yijing Wang
Now msi chip is saved in pci_sys_data in arm,
we could clean the bus->msi assignment in
pci core.

Signed-off-by: Yijing Wang 
CC: Thierry Reding 
CC: Thomas Petazzoni 
---
 drivers/pci/probe.c |1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index efa48dc..98bf4c3 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -682,7 +682,6 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus 
*parent,
 
child->parent = parent;
child->ops = parent->ops;
-   child->msi = parent->msi;
child->sysdata = parent->sysdata;
child->bus_flags = parent->bus_flags;
 
-- 
1.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v3 13/27] x86/xen/MSI: Use MSI chip framework to configure MSI/MSI-X irq

2014-10-14 Thread Yijing Wang
Use MSI chip framework instead of arch MSI functions to configure
MSI/MSI-X irq. So we can manage MSI/MSI-X irq in a unified framework.

Signed-off-by: Yijing Wang 
Acked-by: David Vrabel 
CC: Konrad Rzeszutek Wilk 
---
 arch/x86/pci/xen.c |   58 +++-
 1 files changed, 39 insertions(+), 19 deletions(-)

diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c
index e5b8b78..75067ca 100644
--- a/arch/x86/pci/xen.c
+++ b/arch/x86/pci/xen.c
@@ -157,7 +157,8 @@ static int acpi_register_gsi_xen(struct device *dev, u32 
gsi,
 struct xen_pci_frontend_ops *xen_pci_frontend;
 EXPORT_SYMBOL_GPL(xen_pci_frontend);
 
-static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+static int xen_setup_msi_irqs(struct msi_chip *chip,
+   struct pci_dev *dev, int nvec, int type)
 {
int irq, ret, i;
struct msi_desc *msidesc;
@@ -219,7 +220,8 @@ static void xen_msi_compose_msg(struct pci_dev *pdev, 
unsigned int pirq,
msg->data = XEN_PIRQ_MSI_DATA;
 }
 
-static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+static int xen_hvm_setup_msi_irqs(struct msi_chip *chip,
+   struct pci_dev *dev, int nvec, int type)
 {
int irq, pirq;
struct msi_desc *msidesc;
@@ -267,7 +269,8 @@ error:
 #ifdef CONFIG_XEN_DOM0
 static bool __read_mostly pci_seg_supported = true;
 
-static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+static int xen_initdom_setup_msi_irqs(struct msi_chip *chip,
+   struct pci_dev *dev, int nvec, int type)
 {
int ret = 0;
struct msi_desc *msidesc;
@@ -349,7 +352,8 @@ out:
return ret;
 }
 
-static void xen_initdom_restore_msi_irqs(struct pci_dev *dev)
+static void xen_initdom_restore_msi_irqs(struct msi_chip *chip,
+   struct pci_dev *dev)
 {
int ret = 0;
 
@@ -376,7 +380,13 @@ static void xen_initdom_restore_msi_irqs(struct pci_dev 
*dev)
 }
 #endif
 
-static void xen_teardown_msi_irqs(struct pci_dev *dev)
+static void xen_teardown_msi_irq(struct msi_chip *chip, unsigned int irq)
+{
+   xen_destroy_irq(irq);
+}
+
+static void xen_teardown_msi_irqs(struct msi_chip *chip,
+   struct pci_dev *dev)
 {
struct msi_desc *msidesc;
 
@@ -386,14 +396,22 @@ static void xen_teardown_msi_irqs(struct pci_dev *dev)
else
xen_pci_frontend_disable_msi(dev);
 
-   /* Free the IRQ's and the msidesc using the generic code. */
-   default_teardown_msi_irqs(dev);
-}
+   list_for_each_entry(msidesc, &dev->msi_list, list) {
+   int i, nvec;
+   if (msidesc->irq == 0)
+   continue;
+   if (msidesc->nvec_used)
+   nvec = msidesc->nvec_used;
+   else
+   nvec = 1 << msidesc->msi_attrib.multiple;
+   for (i = 0; i < nvec; i++)
+   xen_teardown_msi_irq(chip, msidesc->irq + i);
+   }
 
-static void xen_teardown_msi_irq(unsigned int irq)
-{
-   xen_destroy_irq(irq);
 }
+
+struct msi_chip xen_msi_chip;
+
 #endif
 
 int __init pci_xen_init(void)
@@ -414,9 +432,9 @@ int __init pci_xen_init(void)
 #endif
 
 #ifdef CONFIG_PCI_MSI
-   x86_msi.setup_msi_irqs = xen_setup_msi_irqs;
-   x86_msi.teardown_msi_irq = xen_teardown_msi_irq;
-   x86_msi.teardown_msi_irqs = xen_teardown_msi_irqs;
+   xen_msi_chip.setup_irqs = xen_setup_msi_irqs;
+   xen_msi_chip.teardown_irqs = xen_teardown_msi_irqs;
+   x86_msi_chip = &xen_msi_chip;
pci_msi_ignore_mask = 1;
 #endif
return 0;
@@ -436,8 +454,9 @@ int __init pci_xen_hvm_init(void)
 #endif
 
 #ifdef CONFIG_PCI_MSI
-   x86_msi.setup_msi_irqs = xen_hvm_setup_msi_irqs;
-   x86_msi.teardown_msi_irq = xen_teardown_msi_irq;
+   xen_msi_chip.setup_irqs = xen_hvm_setup_msi_irqs;
+   xen_msi_chip.teardown_irq = xen_teardown_msi_irq;
+   x86_msi_chip = &xen_msi_chip;
 #endif
return 0;
 }
@@ -494,9 +513,10 @@ int __init pci_xen_initial_domain(void)
int irq;
 
 #ifdef CONFIG_PCI_MSI
-   x86_msi.setup_msi_irqs = xen_initdom_setup_msi_irqs;
-   x86_msi.teardown_msi_irq = xen_teardown_msi_irq;
-   x86_msi.restore_msi_irqs = xen_initdom_restore_msi_irqs;
+   xen_msi_chip.setup_irqs = xen_initdom_setup_msi_irqs;
+   xen_msi_chip.teardown_irq = xen_teardown_msi_irq;
+   xen_msi_chip.restore_irqs = xen_initdom_restore_msi_irqs;
+   x86_msi_chip = &xen_msi_chip;
pci_msi_ignore_mask = 1;
 #endif
xen_setup_acpi_sci();
-- 
1.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v3 00/27] Use MSI chip framework to configure MSI/MSI-X in all platforms

2014-10-14 Thread Yijing Wang
Now there are a lot of weak arch functions in MSI code.
Thierry Reding Introduced MSI chip framework to configure MSI/MSI-X in arm,
that's a better solution than overriding lots of existing weak arch 
functionsin. 
This series use MSI chip framework to refactor MSI code across all platforms 
to eliminate weak arch functions. Then all MSI irqs will be managed in a 
unified framework. Because this series changed a lot of ARCH MSI code, 
so tests in the related platforms are warmly welcomed!

And you may access it at:
https://github.com/YijingWang/msi-chip-v3.git master

v2->v3:
1. For patch "x86/xen/MSI: Eliminate...", introduce a new global flag 
"pci_msi_ignore_mask"
to control the msi mask instead of replacing the irqchip->mask with nop 
function,
the latter method has problem pointed out by Konrad Rzeszutek Wilk.
2. Save msi chip in arch pci sysdata instead of associating msi chip to pci bus.
Because pci devices under same host share the same msi chip, so I think 
associate
msi chip to pci host/pci sysdata is better than to bother every pci bus/devices.
A better solution suggested by Liviu is to rip out pci_host_bridge from 
pci_create_root_bus(), 
then we can save some pci host common attributes like domain_nr, msi_chip, 
resources,
into the generic pci_host_bridge. Because this changes to pci host bridge is 
also 
a large series, so I think we should go step by step, I will try to post it in 
another
series later.
4. Clean up arm pcibios_add_bus() and pcibios_remove_bus() which were used to 
associate
msi chip to pci bus.

v1->v2:
Add a patch to make s390 MSI code build happy between patch "x86/xen/MSI: E.."
and "s390/MSI: Use MSI..". Fix several typo problems found by Lucas.

RFC->v1: 
Updated "[patch 4/21] x86/xen/MSI: Eliminate...", export msi_chip instead
of #ifdef to fix MSI bug in xen running in x86. 
Rename arch_get_match_msi_chip() to arch_find_msi_chip().
Drop use struct device as the msi_chip argument, we will do that
later in another patchset.

Yijing Wang (27):
  MSI: Remove the redundant irq_set_chip_data()
  x86/xen/MSI: Eliminate arch_msix_mask_irq() and arch_msi_mask_irq()
  s390/MSI: Use __msi_mask_irq() instead of default_msi_mask_irq()
  arm/MSI: Save MSI chip in pci_sys_data
  PCI: tegra: Save msi chip in pci_sys_data
  PCI: designware: Save msi chip in pci_sys_data
  PCI: rcar: Save msi chip in pci_sys_data
  PCI: mvebu: Save msi chip in pci_sys_data
  arm/PCI: Clean unused pcibios_add_bus() and pcibios_remove_bus()
  PCI/MSI: Remove useless bus->msi assignment
  PCI/MSI: Refactor struct msi_chip to make it become more common
  x86/MSI: Use MSI chip framework to configure MSI/MSI-X irq
  x86/xen/MSI: Use MSI chip framework to configure MSI/MSI-X irq
  Irq_remapping/MSI: Use MSI chip framework to configure MSI/MSI-X irq
  x86/MSI: Remove unused MSI weak arch functions
  Mips/MSI: Save msi chip in pci sysdata
  MIPS/Octeon/MSI: Use MSI chip framework to configure MSI/MSI-X irq
  MIPS/Xlp: Remove the dead function destroy_irq() to fix build error
  MIPS/Xlp/MSI: Use MSI chip framework to configure MSI/MSI-X irq
  MIPS/Xlr/MSI: Use MSI chip framework to configure MSI/MSI-X irq
  Powerpc/MSI: Use MSI chip framework to configure MSI/MSI-X irq
  s390/MSI: Use MSI chip framework to configure MSI/MSI-X irq
  arm/iop13xx/MSI: Use MSI chip framework to configure MSI/MSI-X irq
  IA64/MSI: Use MSI chip framework to configure MSI/MSI-X irq
  Sparc/MSI: Use MSI chip framework to configure MSI/MSI-X irq
  tile/MSI: Use MSI chip framework to configure MSI/MSI-X irq
  PCI/MSI: Clean up unused MSI arch functions

 arch/arm/include/asm/mach/pci.h |   10 +-
 arch/arm/include/asm/pci.h  |9 ++
 arch/arm/kernel/bios32.c|   19 +---
 arch/arm/mach-iop13xx/include/mach/pci.h|4 +
 arch/arm/mach-iop13xx/iq81340mc.c   |3 +
 arch/arm/mach-iop13xx/iq81340sc.c   |5 +-
 arch/arm/mach-iop13xx/msi.c |   11 ++-
 arch/ia64/include/asm/pci.h |   10 ++
 arch/ia64/kernel/msi_ia64.c |   14 ++-
 arch/ia64/pci/pci.c |1 +
 arch/mips/include/asm/netlogic/xlp-hal/pcibus.h |1 +
 arch/mips/include/asm/octeon/pci-octeon.h   |4 +
 arch/mips/include/asm/pci.h |   14 +++
 arch/mips/pci/msi-octeon.c  |   31 +++---
 arch/mips/pci/msi-xlp.c |   15 ++-
 arch/mips/pci/pci-octeon.c  |3 +
 arch/mips/pci/pci-xlp.c |3 +
 arch/mips/pci/pci-xlr.c |   17 +++-
 arch/powerpc/include/asm/pci-bridge.h   |   15 +++
 arch/powerpc/kernel/msi.c   |   12 ++-
 arch/powerpc/kernel/pci-common.c|3 +
 arch/s390/include/asm/pci.h |9 ++
 arch/s390/pci/pci.c |   16 ++-
 arch/sparc/kernel/pci.c |

[PATCH v3 16/27] Mips/MSI: Save msi chip in pci sysdata

2014-10-14 Thread Yijing Wang
Save msi chip in pci sysdata, add arch pci_find_msi_chip()
to extract out msi chip.

Signed-off-by: Yijing Wang 
---
 arch/mips/include/asm/pci.h |   14 ++
 1 files changed, 14 insertions(+), 0 deletions(-)

diff --git a/arch/mips/include/asm/pci.h b/arch/mips/include/asm/pci.h
index 974b0e3..287661b 100644
--- a/arch/mips/include/asm/pci.h
+++ b/arch/mips/include/asm/pci.h
@@ -43,6 +43,9 @@ struct pci_controller {
 
int iommu;
 
+#ifdef CONFIG_PCI_MSI
+   struct msi_chip *msi_chip;
+#endif
/* Optional access methods for reading/writing the bus number
   of the PCI controller */
int (*get_busno)(void);
@@ -54,6 +57,17 @@ struct pci_controller {
  */
 extern void register_pci_controller(struct pci_controller *hose);
 
+#ifdef CONFIG_PCI_MSI
+
+static inline struct msi_chip *pci_msi_chip(struct pci_bus *bus)
+{
+   struct pci_controller *control = (struct pci_controller *)bus->sysdata;
+
+   return control->msi_chip;
+}
+
+#endif
+
 /*
  * board supplied pci irq fixup routine
  */
-- 
1.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v3 14/27] Irq_remapping/MSI: Use MSI chip framework to configure MSI/MSI-X irq

2014-10-14 Thread Yijing Wang
Use MSI chip framework instead of arch MSI functions to configure
MSI/MSI-X irq. So we can manage MSI/MSI-X irq in a unified framework.

Signed-off-by: Yijing Wang 
---
 drivers/iommu/irq_remapping.c |   11 ---
 1 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/irq_remapping.c b/drivers/iommu/irq_remapping.c
index 33c4395..48d57e9 100644
--- a/drivers/iommu/irq_remapping.c
+++ b/drivers/iommu/irq_remapping.c
@@ -139,8 +139,8 @@ error:
return ret;
 }
 
-static int irq_remapping_setup_msi_irqs(struct pci_dev *dev,
-   int nvec, int type)
+static int irq_remapping_setup_msi_irqs(struct msi_chip *chip,
+   struct pci_dev *dev, int nvec, int type)
 {
if (type == PCI_CAP_ID_MSI)
return do_setup_msi_irqs(dev, nvec);
@@ -148,6 +148,11 @@ static int irq_remapping_setup_msi_irqs(struct pci_dev 
*dev,
return do_setup_msix_irqs(dev, nvec);
 }
 
+static struct msi_chip remap_msi_chip = {
+   .setup_irqs = irq_remapping_setup_msi_irqs,
+   .teardown_irq = native_teardown_msi_irq,
+};
+
 static void eoi_ioapic_pin_remapped(int apic, int pin, int vector)
 {
/*
@@ -165,9 +170,9 @@ static void __init irq_remapping_modify_x86_ops(void)
x86_io_apic_ops.set_affinity= set_remapped_irq_affinity;
x86_io_apic_ops.setup_entry = setup_ioapic_remapped_entry;
x86_io_apic_ops.eoi_ioapic_pin  = eoi_ioapic_pin_remapped;
-   x86_msi.setup_msi_irqs  = irq_remapping_setup_msi_irqs;
x86_msi.setup_hpet_msi  = setup_hpet_msi_remapped;
x86_msi.compose_msi_msg = compose_remapped_msi_msg;
+   x86_msi_chip = &remap_msi_chip;
 }
 
 static __init int setup_nointremap(char *str)
-- 
1.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v3 15/27] x86/MSI: Remove unused MSI weak arch functions

2014-10-14 Thread Yijing Wang
Now we can clean up MSI weak arch functions in x86.

Signed-off-by: Yijing Wang 
---
 arch/x86/include/asm/pci.h  |5 +
 arch/x86/include/asm/x86_init.h |4 
 arch/x86/kernel/apic/io_apic.c  |   21 +
 arch/x86/kernel/x86_init.c  |   24 
 4 files changed, 6 insertions(+), 48 deletions(-)

diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
index f41b58a..3a5cf19 100644
--- a/arch/x86/include/asm/pci.h
+++ b/arch/x86/include/asm/pci.h
@@ -108,14 +108,11 @@ extern void pci_iommu_alloc(void);
 #ifdef CONFIG_PCI_MSI
 /* implemented in arch/x86/kernel/apic/io_apic. */
 struct msi_desc;
-int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type);
-void native_teardown_msi_irq(unsigned int irq);
-void native_restore_msi_irqs(struct pci_dev *dev);
+void native_teardown_msi_irq(struct msi_chip *chip, unsigned int irq);
 int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc,
  unsigned int irq_base, unsigned int irq_offset);
 extern struct msi_chip *x86_msi_chip;
 #else
-#define native_setup_msi_irqs  NULL
 #define native_teardown_msi_irqNULL
 #endif
 
diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h
index f58a9c7..2514f67 100644
--- a/arch/x86/include/asm/x86_init.h
+++ b/arch/x86/include/asm/x86_init.h
@@ -174,13 +174,9 @@ struct pci_dev;
 struct msi_msg;
 
 struct x86_msi_ops {
-   int (*setup_msi_irqs)(struct pci_dev *dev, int nvec, int type);
void (*compose_msi_msg)(struct pci_dev *dev, unsigned int irq,
unsigned int dest, struct msi_msg *msg,
   u8 hpet_id);
-   void (*teardown_msi_irq)(unsigned int irq);
-   void (*teardown_msi_irqs)(struct pci_dev *dev);
-   void (*restore_msi_irqs)(struct pci_dev *dev);
int  (*setup_hpet_msi)(unsigned int irq, unsigned int id);
 };
 
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index ec79b38..11d353f 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -3200,7 +3200,8 @@ int setup_msi_irq(struct pci_dev *dev, struct msi_desc 
*msidesc,
return 0;
 }
 
-int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+static int native_setup_msi_irqs(struct msi_chip *chip,
+   struct pci_dev *dev, int nvec, int type)
 {
struct msi_desc *msidesc;
unsigned int irq;
@@ -3227,26 +3228,14 @@ int native_setup_msi_irqs(struct pci_dev *dev, int 
nvec, int type)
return 0;
 }
 
-static int __native_setup_msi_irqs(struct msi_chip *chip, 
-   struct pci_dev *dev, int nvec, int type)
-{
-   return native_setup_msi_irqs(dev, nvec, type);
-}
-
-void native_teardown_msi_irq(unsigned int irq)
+void native_teardown_msi_irq(struct msi_chip *chip, unsigned int irq)
 {
irq_free_hwirq(irq);
 }
 
-static void __native_teardown_msi_irq(struct msi_chip *chip, 
-   unsigned int irq)
-{
-   native_teardown_msi_irq(irq);
-}
-
 static struct msi_chip native_msi_chip = {
-   .setup_irqs = __native_setup_msi_irqs,
-   .teardown_irq = __native_teardown_msi_irq,
+   .setup_irqs = native_setup_msi_irqs,
+   .teardown_irq = native_teardown_msi_irq,
 };
 
 struct msi_chip *x86_msi_chip = &native_msi_chip;
diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c
index 234b072..cc32568 100644
--- a/arch/x86/kernel/x86_init.c
+++ b/arch/x86/kernel/x86_init.c
@@ -110,34 +110,10 @@ EXPORT_SYMBOL_GPL(x86_platform);
 
 #if defined(CONFIG_PCI_MSI)
 struct x86_msi_ops x86_msi = {
-   .setup_msi_irqs = native_setup_msi_irqs,
.compose_msi_msg= native_compose_msi_msg,
-   .teardown_msi_irq   = native_teardown_msi_irq,
-   .teardown_msi_irqs  = default_teardown_msi_irqs,
-   .restore_msi_irqs   = default_restore_msi_irqs,
.setup_hpet_msi = default_setup_hpet_msi,
 };
 
-/* MSI arch specific hooks */
-int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
-{
-   return x86_msi.setup_msi_irqs(dev, nvec, type);
-}
-
-void arch_teardown_msi_irqs(struct pci_dev *dev)
-{
-   x86_msi.teardown_msi_irqs(dev);
-}
-
-void arch_teardown_msi_irq(unsigned int irq)
-{
-   x86_msi.teardown_msi_irq(irq);
-}
-
-void arch_restore_msi_irqs(struct pci_dev *dev)
-{
-   x86_msi.restore_msi_irqs(dev);
-}
 #endif
 
 struct x86_io_apic_ops x86_io_apic_ops = {
-- 
1.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v3 01/27] MSI: Remove the redundant irq_set_chip_data()

2014-10-14 Thread Yijing Wang
Currently, pcie-designware, pcie-rcar and pci-tegra drivers
use irq chip_data to save the msi_chip pointer. They
already call irq_set_chip_data() in their own MSI irq map
functions. And chip_data is an opaque pointer, how to use
it is arch dependent. It should not be placed in MSI core.

Signed-off-by: Yijing Wang 
Reviewed-by: Thierry Reding 
---
 drivers/pci/msi.c |5 ++---
 1 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 2f7c92c..ecb92a5 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -41,14 +41,13 @@ int __weak arch_setup_msi_irq(struct pci_dev *dev, struct 
msi_desc *desc)
if (err < 0)
return err;
 
-   irq_set_chip_data(desc->irq, chip);
-
return 0;
 }
 
 void __weak arch_teardown_msi_irq(unsigned int irq)
 {
-   struct msi_chip *chip = irq_get_chip_data(irq);
+   struct msi_desc *entry = irq_get_msi_desc(irq);
+   struct msi_chip *chip = entry->dev->bus->msi;
 
if (!chip || !chip->teardown_irq)
return;
-- 
1.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v3 17/27] MIPS/Octeon/MSI: Use MSI chip framework to configure MSI/MSI-X irq

2014-10-14 Thread Yijing Wang
Use MSI chip framework instead of arch MSI functions to configure
MSI/MSI-X irq. So we can manage MSI/MSI-X irq in a unified framework.

Signed-off-by: Yijing Wang 
---
 arch/mips/include/asm/octeon/pci-octeon.h |4 +++
 arch/mips/pci/msi-octeon.c|   31 
 arch/mips/pci/pci-octeon.c|3 ++
 3 files changed, 25 insertions(+), 13 deletions(-)

diff --git a/arch/mips/include/asm/octeon/pci-octeon.h 
b/arch/mips/include/asm/octeon/pci-octeon.h
index 64ba56a..27ffe42 100644
--- a/arch/mips/include/asm/octeon/pci-octeon.h
+++ b/arch/mips/include/asm/octeon/pci-octeon.h
@@ -66,4 +66,8 @@ enum octeon_dma_bar_type {
  */
 extern enum octeon_dma_bar_type octeon_dma_bar_type;
 
+#ifdef CONFIG_PCI_MSI
+extern struct msi_chip octeon_msi_chip;
+#endif
+
 #endif
diff --git a/arch/mips/pci/msi-octeon.c b/arch/mips/pci/msi-octeon.c
index 63bbe07..fd4d698 100644
--- a/arch/mips/pci/msi-octeon.c
+++ b/arch/mips/pci/msi-octeon.c
@@ -57,7 +57,7 @@ static int msi_irq_size;
  *
  * Returns 0 on success.
  */
-int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
+static int octeon_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
 {
struct msi_msg msg;
u16 control;
@@ -132,12 +132,12 @@ msi_irq_allocated:
/* Make sure the search for available interrupts didn't fail */
if (irq >= 64) {
if (request_private_bits) {
-   pr_err("arch_setup_msi_irq: Unable to find %d free 
interrupts, trying just one",
-  1 << request_private_bits);
+   pr_err("%s: Unable to find %d free interrupts, trying 
just one",
+  __func__, 1 << request_private_bits);
request_private_bits = 0;
goto try_only_one;
} else
-   panic("arch_setup_msi_irq: Unable to find a free MSI 
interrupt");
+   panic("%s: Unable to find a free MSI interrupt", 
__func__);
}
 
/* MSI interrupts start at logical IRQ OCTEON_IRQ_MSI_BIT0 */
@@ -168,7 +168,7 @@ msi_irq_allocated:
msg.address_hi = (0 + CVMX_SLI_PCIE_MSI_RCV) >> 32;
break;
default:
-   panic("arch_setup_msi_irq: Invalid octeon_dma_bar_type");
+   panic("%s: Invalid octeon_dma_bar_type", __func__);
}
msg.data = irq - OCTEON_IRQ_MSI_BIT0;
 
@@ -182,7 +182,8 @@ msi_irq_allocated:
return 0;
 }
 
-int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+static int octeon_setup_msi_irqs(struct msi_chip *chip, struct pci_dev *dev,
+   int nvec, int type)
 {
struct msi_desc *entry;
int ret;
@@ -201,7 +202,7 @@ int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int 
type)
return 1;
 
list_for_each_entry(entry, &dev->msi_list, list) {
-   ret = arch_setup_msi_irq(dev, entry);
+   ret = octeon_setup_msi_irq(dev, entry);
if (ret < 0)
return ret;
if (ret > 0)
@@ -210,14 +211,13 @@ int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, 
int type)
 
return 0;
 }
-
 /**
  * Called when a device no longer needs its MSI interrupts. All
  * MSI interrupts for the device are freed.
  *
  * @irq:The devices first irq number. There may be multple in sequence.
  */
-void arch_teardown_msi_irq(unsigned int irq)
+static void octeon_teardown_msi_irq(struct msi_chip *chip, unsigned int irq)
 {
int number_irqs;
u64 bitmask;
@@ -226,8 +226,8 @@ void arch_teardown_msi_irq(unsigned int irq)
 
if ((irq < OCTEON_IRQ_MSI_BIT0)
|| (irq > msi_irq_size + OCTEON_IRQ_MSI_BIT0))
-   panic("arch_teardown_msi_irq: Attempted to teardown illegal "
- "MSI interrupt (%d)", irq);
+   panic("%s: Attempted to teardown illegal "
+   "MSI interrupt (%d)", __func__, irq);
 
irq -= OCTEON_IRQ_MSI_BIT0;
index = irq / 64;
@@ -249,8 +249,8 @@ void arch_teardown_msi_irq(unsigned int irq)
/* Shift the mask to the correct bit location */
bitmask <<= irq0;
if ((msi_free_irq_bitmask[index] & bitmask) != bitmask)
-   panic("arch_teardown_msi_irq: Attempted to teardown MSI "
- "interrupt (%d) not in use", irq);
+   panic("%s: Attempted to teardown MSI "
+   "interrupt (%d) not in use", __func__, irq);
 
/* Checks are done, update the in use bitmask */
spin_lock(&msi_free_irq_bitmask_lock);
@@ -259,6 +259,11 @@ void arch_teardown_msi_irq(unsigned int irq)
spin_unlock(&msi_free_irq_bitmask_lock);
 }
 
+struct msi_chip octeon_msi_chip = {
+   .setup_irqs = octeon_setup_msi_irqs,
+   .teardown_irq = octeon_teardown_msi_irq,
+};
+
 static DEFINE_RAW_SPINLOCK(octeon_irq_

[PATCH v3 25/27] Sparc/MSI: Use MSI chip framework to configure MSI/MSI-X irq

2014-10-14 Thread Yijing Wang
Use MSI chip framework instead of arch MSI functions to configure
MSI/MSI-X irq. So we can manage MSI/MSI-X irq in a unified framework.

Signed-off-by: Yijing Wang 
---
 arch/sparc/kernel/pci.c  |   14 --
 arch/sparc/kernel/pci_impl.h |   12 
 2 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c
index b36365f..a46a148 100644
--- a/arch/sparc/kernel/pci.c
+++ b/arch/sparc/kernel/pci.c
@@ -656,6 +656,9 @@ struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm,
 
printk("PCI: Scanning PBM %s\n", node->full_name);
 
+#ifdef CONFIG_PCI_MSI
+   pbm->msi_chip = &sparc_msi_chip;
+#endif
pci_add_resource_offset(&resources, &pbm->io_space,
pbm->io_space.start);
pci_add_resource_offset(&resources, &pbm->mem_space,
@@ -905,7 +908,8 @@ int pci_domain_nr(struct pci_bus *pbus)
 EXPORT_SYMBOL(pci_domain_nr);
 
 #ifdef CONFIG_PCI_MSI
-int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
+static int sparc_setup_msi_irq(struct msi_chip *chip,
+   struct pci_dev *pdev, struct msi_desc *desc)
 {
struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller;
unsigned int irq;
@@ -916,7 +920,7 @@ int arch_setup_msi_irq(struct pci_dev *pdev, struct 
msi_desc *desc)
return pbm->setup_msi_irq(&irq, pdev, desc);
 }
 
-void arch_teardown_msi_irq(unsigned int irq)
+static void sparc_teardown_msi_irq(struct msi_chip *chip, unsigned int irq)
 {
struct msi_desc *entry = irq_get_msi_desc(irq);
struct pci_dev *pdev = entry->dev;
@@ -925,6 +929,12 @@ void arch_teardown_msi_irq(unsigned int irq)
if (pbm->teardown_msi_irq)
pbm->teardown_msi_irq(irq, pdev);
 }
+
+struct msi_chip sparc_msi_chip = {
+   .setup_irq = sparc_setup_msi_irq,
+   .teardown_irq = sparc_teardown_msi_irq,
+};
+
 #endif /* !(CONFIG_PCI_MSI) */
 
 static void ali_sound_dma_hack(struct pci_dev *pdev, int set_bit)
diff --git a/arch/sparc/kernel/pci_impl.h b/arch/sparc/kernel/pci_impl.h
index 75803c7..073bb4e 100644
--- a/arch/sparc/kernel/pci_impl.h
+++ b/arch/sparc/kernel/pci_impl.h
@@ -55,6 +55,8 @@ struct sparc64_msiq_cookie {
struct pci_pbm_info *pbm;
unsigned long msiqid;
 };
+
+extern struct msi_chip sparc_msi_chip;
 #endif
 
 struct pci_pbm_info {
@@ -132,6 +134,7 @@ struct pci_pbm_info {
void*msi_queues;
unsigned long   *msi_bitmap;
unsigned int*msi_irq_table;
+   struct msi_chip *msi_chip;
int (*setup_msi_irq)(unsigned int *irq_p, struct pci_dev *pdev,
 struct msi_desc *entry);
void (*teardown_msi_irq)(unsigned int irq, struct pci_dev *pdev);
@@ -153,6 +156,15 @@ struct pci_pbm_info {
int numa_node;
 };
 
+#ifdef CONFIG_PCI_MSI
+static inline struct msi_chip *pci_msi_chip(struct pci_bus *bus)
+{
+   struct pci_pbm_info *pbm = bus->sysdata;
+
+   return pbm->msi_chip;
+}
+#endif
+
 extern struct pci_pbm_info *pci_pbm_root;
 
 extern int pci_num_pbms;
-- 
1.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v3 21/27] Powerpc/MSI: Use MSI chip framework to configure MSI/MSI-X irq

2014-10-14 Thread Yijing Wang
Use MSI chip framework instead of arch MSI functions to configure
MSI/MSI-X irq. So we can manage MSI/MSI-X irq in a unified framework.

Signed-off-by: Yijing Wang 
---
Hi Michael,
   I dropped the Acked-by , because this version has a
lot changes compared to last. So, I guess you may want to check it again.
---
 arch/powerpc/include/asm/pci-bridge.h |   15 +++
 arch/powerpc/kernel/msi.c |   12 ++--
 arch/powerpc/kernel/pci-common.c  |3 +++
 3 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/include/asm/pci-bridge.h 
b/arch/powerpc/include/asm/pci-bridge.h
index 4ca90a3..233553e 100644
--- a/arch/powerpc/include/asm/pci-bridge.h
+++ b/arch/powerpc/include/asm/pci-bridge.h
@@ -32,6 +32,10 @@ struct pci_controller {
int self_busno;
struct resource busn;
 
+#ifdef CONFIG_PCI_MSI
+   struct msi_chip *msi_chip;
+#endif
+
void __iomem *io_base_virt;
 #ifdef CONFIG_PPC64
void *io_base_alloc;
@@ -94,6 +98,17 @@ struct pci_controller {
void *private_data;
 };
 
+#ifdef CONFIG_PCI_MSI
+extern struct msi_chip ppc_msi_chip;
+
+static inline struct msi_chip *pci_msi_chip(struct pci_bus *bus)
+{
+   struct pci_controller *hose = bus->sysdata;
+
+   return hose->msi_chip;
+}
+#endif
+
 /* These are used for config access before all the PCI probing
has been done. */
 extern int early_read_config_byte(struct pci_controller *hose, int bus,
diff --git a/arch/powerpc/kernel/msi.c b/arch/powerpc/kernel/msi.c
index 71bd161..f38b67c 100644
--- a/arch/powerpc/kernel/msi.c
+++ b/arch/powerpc/kernel/msi.c
@@ -13,7 +13,8 @@
 
 #include 
 
-int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+static int ppc_setup_msi_irqs(struct msi_chip *chip,
+   struct pci_dev *dev, int nvec, int type)
 {
if (!ppc_md.setup_msi_irqs || !ppc_md.teardown_msi_irqs) {
pr_debug("msi: Platform doesn't provide MSI callbacks.\n");
@@ -27,7 +28,13 @@ int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int 
type)
return ppc_md.setup_msi_irqs(dev, nvec, type);
 }
 
-void arch_teardown_msi_irqs(struct pci_dev *dev)
+static void ppc_teardown_msi_irqs(struct msi_chip *chip,
+   struct pci_dev *dev)
 {
ppc_md.teardown_msi_irqs(dev);
 }
+
+struct msi_chip ppc_msi_chip = {
+   .setup_irqs = ppc_setup_msi_irqs,
+   .teardown_irqs = ppc_teardown_msi_irqs,
+};
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index b2814e2..9f18b42 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -1594,6 +1594,9 @@ void pcibios_scan_phb(struct pci_controller *hose)
/* Wire up PHB bus resources */
pcibios_setup_phb_resources(hose, &resources);
 
+#ifdef CONFIG_PCI_MSI
+   hose->msi_chip = &ppc_msi_chip;
+#endif
hose->busn.start = hose->first_busno;
hose->busn.end   = hose->last_busno;
hose->busn.flags = IORESOURCE_BUS;
-- 
1.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v3 26/27] tile/MSI: Use MSI chip framework to configure MSI/MSI-X irq

2014-10-14 Thread Yijing Wang
Use MSI chip framework instead of arch MSI functions to configure
MSI/MSI-X irq. So we can manage MSI/MSI-X irq in a unified framework.

Signed-off-by: Yijing Wang 
---
 arch/tile/include/asm/pci.h |   10 ++
 arch/tile/kernel/pci_gx.c   |   13 +++--
 2 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/arch/tile/include/asm/pci.h b/arch/tile/include/asm/pci.h
index dfedd7a..d27d9ec 100644
--- a/arch/tile/include/asm/pci.h
+++ b/arch/tile/include/asm/pci.h
@@ -152,6 +152,7 @@ struct pci_controller {
int pio_io_index;   /* PIO region index for I/O space access */
 #endif
 
+   struct msi_chip *msi_chip;
/*
 * Mem-Map regions for all the memory controllers so that Linux can
 * map all of its physical memory space to the PCI bus.
@@ -179,6 +180,15 @@ struct pci_controller {
int irq_intx_table[4];
 };
 
+extern struct msi_chip tilegx_msi;
+
+static inline struct msi_chip *pci_msi_chip(struct pci_bus *bus)
+{
+   struct pci_controller *controller = bus->sysdata;
+
+   return controller->msi_chip;
+}
+
 extern struct pci_controller pci_controllers[TILEGX_NUM_TRIO * 
TILEGX_TRIO_PCIES];
 extern gxio_trio_context_t trio_contexts[TILEGX_NUM_TRIO];
 extern int num_trio_shims;
diff --git a/arch/tile/kernel/pci_gx.c b/arch/tile/kernel/pci_gx.c
index e39f9c5..ba66517 100644
--- a/arch/tile/kernel/pci_gx.c
+++ b/arch/tile/kernel/pci_gx.c
@@ -887,6 +887,7 @@ int __init pcibios_init(void)
controller->mem_offset);
pci_add_resource(&resources, &controller->io_space);
controller->first_busno = next_busno;
+   controller->msi_chip = &tilegx_msi;
bus = pci_scan_root_bus(NULL, next_busno, controller->ops,
controller, &resources);
controller->root_bus = bus;
@@ -1485,7 +1486,8 @@ static struct irq_chip tilegx_msi_chip = {
/* TBD: support set_affinity. */
 };
 
-int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
+static int tile_setup_msi_irq(struct msi_chip *chip,
+   struct pci_dev *pdev, struct msi_desc *desc)
 {
struct pci_controller *controller;
gxio_trio_context_t *trio_context;
@@ -1604,7 +1606,12 @@ is_64_failure:
return ret;
 }
 
-void arch_teardown_msi_irq(unsigned int irq)
+static void tile_teardown_msi_irq(struct msi_chip *chip, unsigned int irq)
 {
irq_free_hwirq(irq);
 }
+
+struct msi_chip tilegx_msi = {
+   .setup_irq = tile_setup_msi_irq,
+   .teardown_irq = tile_teardown_msi_irq,
+};
-- 
1.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v3 18/27] MIPS/Xlp: Remove the dead function destroy_irq() to fix build error

2014-10-14 Thread Yijing Wang
Commit 465665f78a7 ("mips: Kill pointless destroy_irq()") removed
the destroy_irq(). So remove the leftover one in xlp_setup_msix()
to fix build error.

arch/mips/pci/msi-xlp.c: In function 'xlp_setup_msix':
arch/mips/pci/msi-xlp.c:447:3: error: implicit declaration of function 
'destroy_irq'..
cc1: some warnings being treated as errors
make[1]: *** [arch/mips/pci/msi-xlp.o] Error 1
make: *** [arch/mips/pci/] Error 2

Signed-off-by: Yijing Wang 
Cc: Thomas Gleixner 
---
 arch/mips/pci/msi-xlp.c |4 +---
 1 files changed, 1 insertions(+), 3 deletions(-)

diff --git a/arch/mips/pci/msi-xlp.c b/arch/mips/pci/msi-xlp.c
index fa374fe..e469dc7 100644
--- a/arch/mips/pci/msi-xlp.c
+++ b/arch/mips/pci/msi-xlp.c
@@ -443,10 +443,8 @@ static int xlp_setup_msix(uint64_t lnkbase, int node, int 
link,
msg.data = 0xc00 | msixvec;
 
ret = irq_set_msi_desc(xirq, desc);
-   if (ret < 0) {
-   destroy_irq(xirq);
+   if (ret < 0)
return ret;
-   }
 
write_msi_msg(xirq, &msg);
return 0;
-- 
1.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v3 02/27] x86/xen/MSI: Eliminate arch_msix_mask_irq() and arch_msi_mask_irq()

2014-10-14 Thread Yijing Wang
Commit 0e4ccb1505a9 ("PCI: Add x86_msi.msi_mask_irq() and msix_mask_irq()")
introduced two __weak arch functions arch_msix_mask_irq() and
arch_msi_mask_irq() to work around a bug when running xen in x86.
These two functions made msi code more complex. This patch reverts
the commit and introduces a global flag to control msi mask action to
avoid the bug. The patch is also preparation for using MSI chip framework
instead of weak arch MSI functions in all platforms. Keep default_msi_mask_irq()
and default_msix_mask_irq() in linux/msi.h to make s390 MSI code compile
happy, they will be removed in the later patch.

Signed-off-by: Yijing Wang 
CC: David Vrabel 
CC: Konrad Rzeszutek Wilk 
---
Hi David and Konrad,
   I dropped the Acked-by and tested-by, because this version has a
lot changes compared to last. So, I guess you may want to check it again.
---
 arch/x86/include/asm/x86_init.h |3 ---
 arch/x86/kernel/x86_init.c  |   10 --
 arch/x86/pci/xen.c  |   14 ++
 drivers/pci/msi.c   |   29 -
 include/linux/msi.h |8 ++--
 5 files changed, 20 insertions(+), 44 deletions(-)

diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h
index e45e4da..f58a9c7 100644
--- a/arch/x86/include/asm/x86_init.h
+++ b/arch/x86/include/asm/x86_init.h
@@ -172,7 +172,6 @@ struct x86_platform_ops {
 
 struct pci_dev;
 struct msi_msg;
-struct msi_desc;
 
 struct x86_msi_ops {
int (*setup_msi_irqs)(struct pci_dev *dev, int nvec, int type);
@@ -183,8 +182,6 @@ struct x86_msi_ops {
void (*teardown_msi_irqs)(struct pci_dev *dev);
void (*restore_msi_irqs)(struct pci_dev *dev);
int  (*setup_hpet_msi)(unsigned int irq, unsigned int id);
-   u32 (*msi_mask_irq)(struct msi_desc *desc, u32 mask, u32 flag);
-   u32 (*msix_mask_irq)(struct msi_desc *desc, u32 flag);
 };
 
 struct IO_APIC_route_entry;
diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c
index e48b674..234b072 100644
--- a/arch/x86/kernel/x86_init.c
+++ b/arch/x86/kernel/x86_init.c
@@ -116,8 +116,6 @@ struct x86_msi_ops x86_msi = {
.teardown_msi_irqs  = default_teardown_msi_irqs,
.restore_msi_irqs   = default_restore_msi_irqs,
.setup_hpet_msi = default_setup_hpet_msi,
-   .msi_mask_irq   = default_msi_mask_irq,
-   .msix_mask_irq  = default_msix_mask_irq,
 };
 
 /* MSI arch specific hooks */
@@ -140,14 +138,6 @@ void arch_restore_msi_irqs(struct pci_dev *dev)
 {
x86_msi.restore_msi_irqs(dev);
 }
-u32 arch_msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag)
-{
-   return x86_msi.msi_mask_irq(desc, mask, flag);
-}
-u32 arch_msix_mask_irq(struct msi_desc *desc, u32 flag)
-{
-   return x86_msi.msix_mask_irq(desc, flag);
-}
 #endif
 
 struct x86_io_apic_ops x86_io_apic_ops = {
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c
index 093f5f4..e5b8b78 100644
--- a/arch/x86/pci/xen.c
+++ b/arch/x86/pci/xen.c
@@ -394,14 +394,6 @@ static void xen_teardown_msi_irq(unsigned int irq)
 {
xen_destroy_irq(irq);
 }
-static u32 xen_nop_msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag)
-{
-   return 0;
-}
-static u32 xen_nop_msix_mask_irq(struct msi_desc *desc, u32 flag)
-{
-   return 0;
-}
 #endif
 
 int __init pci_xen_init(void)
@@ -425,8 +417,7 @@ int __init pci_xen_init(void)
x86_msi.setup_msi_irqs = xen_setup_msi_irqs;
x86_msi.teardown_msi_irq = xen_teardown_msi_irq;
x86_msi.teardown_msi_irqs = xen_teardown_msi_irqs;
-   x86_msi.msi_mask_irq = xen_nop_msi_mask_irq;
-   x86_msi.msix_mask_irq = xen_nop_msix_mask_irq;
+   pci_msi_ignore_mask = 1;
 #endif
return 0;
 }
@@ -506,8 +497,7 @@ int __init pci_xen_initial_domain(void)
x86_msi.setup_msi_irqs = xen_initdom_setup_msi_irqs;
x86_msi.teardown_msi_irq = xen_teardown_msi_irq;
x86_msi.restore_msi_irqs = xen_initdom_restore_msi_irqs;
-   x86_msi.msi_mask_irq = xen_nop_msi_mask_irq;
-   x86_msi.msix_mask_irq = xen_nop_msix_mask_irq;
+   pci_msi_ignore_mask = 1;
 #endif
xen_setup_acpi_sci();
__acpi_register_gsi = acpi_register_gsi_xen;
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index ecb92a5..22e413c 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -23,6 +23,7 @@
 #include "pci.h"
 
 static int pci_msi_enable = 1;
+int pci_msi_ignore_mask;
 
 #define msix_table_size(flags) ((flags & PCI_MSIX_FLAGS_QSIZE) + 1)
 
@@ -162,11 +163,11 @@ static inline __attribute_const__ u32 msi_mask(unsigned x)
  * reliably as devices without an INTx disable bit will then generate a
  * level IRQ which will never be cleared.
  */
-u32 default_msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag)
+u32 __msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag)
 {
u32 mask_bits = desc->masked;
 
-   if (!desc->msi_attrib.maskbit)
+   if (pci_msi_ignore_mask || !desc-

[PATCH v3 07/27] PCI: rcar: Save msi chip in pci_sys_data

2014-10-14 Thread Yijing Wang
Save msi chip in pci_sys_data instead of assign
msi chip to every pci bus in .add_bus().

Signed-off-by: Yijing Wang 
---
 drivers/pci/host/pcie-rcar.c |   13 +++--
 1 files changed, 3 insertions(+), 10 deletions(-)

diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
index 61158e0..c999c7e 100644
--- a/drivers/pci/host/pcie-rcar.c
+++ b/drivers/pci/host/pcie-rcar.c
@@ -380,20 +380,10 @@ static int rcar_pcie_setup(int nr, struct pci_sys_data 
*sys)
return 1;
 }
 
-static void rcar_pcie_add_bus(struct pci_bus *bus)
-{
-   if (IS_ENABLED(CONFIG_PCI_MSI)) {
-   struct rcar_pcie *pcie = sys_to_pcie(bus->sysdata);
-
-   bus->msi = &pcie->msi.chip;
-   }
-}
-
 struct hw_pci rcar_pci = {
.setup  = rcar_pcie_setup,
.map_irq= of_irq_parse_and_map_pci,
.ops= &rcar_pcie_ops,
-   .add_bus= rcar_pcie_add_bus,
 };
 
 static void rcar_pcie_enable(struct rcar_pcie *pcie)
@@ -402,6 +392,9 @@ static void rcar_pcie_enable(struct rcar_pcie *pcie)
 
rcar_pci.nr_controllers = 1;
rcar_pci.private_data = (void **)&pcie;
+#ifdef CONFIG_PCI_MSI
+   rcar_pci.msi_chip = &pcie->msi.chip;
+#endif
 
pci_common_init_dev(&pdev->dev, &rcar_pci);
 #ifdef CONFIG_PCI_DOMAINS
-- 
1.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v3 06/27] PCI: designware: Save msi chip in pci_sys_data

2014-10-14 Thread Yijing Wang
Save msi chip in pci_sys_data instead of assign
msi chip to every pci bus in .add_bus().

Signed-off-by: Yijing Wang 
---
 drivers/pci/host/pcie-designware.c |   15 ---
 1 files changed, 4 insertions(+), 11 deletions(-)

diff --git a/drivers/pci/host/pcie-designware.c 
b/drivers/pci/host/pcie-designware.c
index dfed00a..56fa8ab 100644
--- a/drivers/pci/host/pcie-designware.c
+++ b/drivers/pci/host/pcie-designware.c
@@ -498,6 +498,10 @@ int __init dw_pcie_host_init(struct pcie_port *pp)
val |= PORT_LOGIC_SPEED_CHANGE;
dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
 
+#ifdef CONFIG_PCI_MSI
+   dw_pcie_msi_chip.dev = pp->dev;
+   dw_pci.msi_chip = &dw_pcie_msi_chip;
+#endif
dw_pci.nr_controllers = 1;
dw_pci.private_data = (void **)&pp;
 
@@ -747,21 +751,10 @@ static int dw_pcie_map_irq(const struct pci_dev *dev, u8 
slot, u8 pin)
return irq;
 }
 
-static void dw_pcie_add_bus(struct pci_bus *bus)
-{
-   if (IS_ENABLED(CONFIG_PCI_MSI)) {
-   struct pcie_port *pp = sys_to_pcie(bus->sysdata);
-
-   dw_pcie_msi_chip.dev = pp->dev;
-   bus->msi = &dw_pcie_msi_chip;
-   }
-}
-
 static struct hw_pci dw_pci = {
.setup  = dw_pcie_setup,
.scan   = dw_pcie_scan_bus,
.map_irq= dw_pcie_map_irq,
-   .add_bus= dw_pcie_add_bus,
 };
 
 void dw_pcie_setup_rc(struct pcie_port *pp)
-- 
1.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v6 1/2] iopoll: Introduce memory-mapped IO polling macros

2014-10-14 Thread Mitchel Humpherys
From: Matt Wagantall 

It is sometimes necessary to poll a memory-mapped register until its value
satisfies some condition. Introduce a family of convenience macros that do
this. Tight-looping, sleeping, and timing out can all be accomplished using
these macros.

Cc: Thierry Reding 
Cc: Will Deacon 
Signed-off-by: Matt Wagantall 
Signed-off-by: Mitchel Humpherys 
---
Changes since v5:
  - Use a shift instead of a divide in the poll loop.
---
 include/linux/iopoll.h | 213 +
 1 file changed, 213 insertions(+)
 create mode 100644 include/linux/iopoll.h

diff --git a/include/linux/iopoll.h b/include/linux/iopoll.h
new file mode 100644
index 00..21dd41942b
--- /dev/null
+++ b/include/linux/iopoll.h
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _LINUX_IOPOLL_H
+#define _LINUX_IOPOLL_H
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/**
+ * readx_poll_timeout - Periodically poll an address until a condition is met 
or a timeout occurs
+ * @op: accessor function (takes @addr as its only argument)
+ * @addr: Address to poll
+ * @val: Variable to read the value into
+ * @cond: Break condition (usually involving @val)
+ * @sleep_us: Maximum time to sleep between reads in us (0 tight-loops)
+ * @timeout_us: Timeout in us, 0 means never timeout
+ *
+ * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
+ * case, the last read value at @addr is stored in @val. Must not
+ * be called from atomic context if sleep_us or timeout_us are used.
+ *
+ * Generally you'll want to use one of the specialized macros defined below
+ * rather than this macro directly.
+ */
+#define readx_poll_timeout(op, addr, val, cond, sleep_us, timeout_us)  \
+({ \
+   ktime_t timeout = ktime_add_us(ktime_get(), timeout_us); \
+   might_sleep_if(sleep_us); \
+   for (;;) { \
+   (val) = op(addr); \
+   if (cond) \
+   break; \
+   if (timeout_us && ktime_compare(ktime_get(), timeout) > 0) { \
+   (val) = op(addr); \
+   break; \
+   } \
+   if (sleep_us) \
+   usleep_range((sleep_us >> 2) + 1, sleep_us); \
+   } \
+   (cond) ? 0 : -ETIMEDOUT; \
+})
+
+/**
+ * readx_poll_timeout_atomic - Periodically poll an address until a condition 
is met or a timeout occurs
+ * @op: accessor function (takes @addr as its only argument)
+ * @addr: Address to poll
+ * @val: Variable to read the value into
+ * @cond: Break condition (usually involving @val)
+ * @delay_us: Time to udelay between reads in us (0 tight-loops)
+ * @timeout_us: Timeout in us, 0 means never timeout
+ *
+ * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
+ * case, the last read value at @addr is stored in @val.
+ *
+ * Generally you'll want to use one of the specialized macros defined below
+ * rather than this macro directly.
+ */
+#define readx_poll_timeout_atomic(op, addr, val, cond, delay_us, timeout_us) \
+({ \
+   ktime_t timeout = ktime_add_us(ktime_get(), timeout_us); \
+   for (;;) { \
+   (val) = op(addr); \
+   if (cond) \
+   break; \
+   if (timeout_us && ktime_compare(ktime_get(), timeout) > 0) { \
+   (val) = op(addr); \
+   break; \
+   } \
+   if (delay_us) \
+   udelay(delay_us);   \
+   } \
+   (cond) ? 0 : -ETIMEDOUT; \
+})
+
+
+#define readl_poll_timeout(addr, val, cond, delay_us, timeout_us) \
+   readx_poll_timeout(readl, addr, val, cond, delay_us, timeout_us)
+
+#define readl_poll_timeout_atomic(addr, val, cond, delay_us, timeout_us) \
+   readx_poll_timeout_atomic(readl, addr, val, cond, delay_us, timeout_us)
+
+#define readb_poll_timeout(addr, val, cond, delay_us, timeout_us) \
+   readx_poll_timeout(readb, addr, val, cond, delay_us, timeout_us)
+
+#define readb_poll_timeout_atomic(addr, val, cond, delay_us, timeout_us) \
+   readx_poll_timeout_atomic(readb, addr, val, cond, delay_us, timeout_us)
+
+#define readw_poll_timeout(addr, val, cond, delay_us, timeout_us) \
+   readx_poll_timeout(readw, addr, val, cond, delay_us, timeout_us)
+
+#define readw_poll_timeout_atomic(addr, val, cond, delay_us, timeout_us) \
+   readx_poll_timeout_atomic(readw, addr, val, cond, delay_us, timeout_us)
+
+#define readq_

[PATCH v6 0/2] iommu/arm-smmu: hard iova_to_phys

2014-10-14 Thread Mitchel Humpherys
This series introduces support for performing iova-to-phys translations via
the ARM SMMU hardware on supported implementations. We also make use of
some new generic macros for polling hardware registers.

v5..v6:

  - iopoll: use shift instead of divide
  - arm-smmu: no changes, resending series due to iopoll change.

v4..v5:

  - iopoll: Added support for other accessor functions
  - iopoll: Unified atomic and non-atomic interfaces
  - iopoll: Fixed erroneous `might_sleep'
  - arm-smmu: Lowered timeout and moved to new iopoll atomic interface

v3..v4:

  - Updated the iopoll commit message to reflect the patch better
  - Added locking around address translation op
  - Return 0 on iova_to_phys failure

v2..v3:

  - Removed unnecessary `dev_name's

v1..v2:

  - Renamed one of the iopoll macros to use the more standard `_atomic'
suffix
  - Removed some convenience iopoll wrappers to encourage explicitness


Matt Wagantall (1):
  iopoll: Introduce memory-mapped IO polling macros

Mitchel Humpherys (1):
  iommu/arm-smmu: add support for iova_to_phys through ATS1PR

 drivers/iommu/arm-smmu.c |  79 +-
 include/linux/iopoll.h   | 213 +++
 2 files changed, 291 insertions(+), 1 deletion(-)
 create mode 100644 include/linux/iopoll.h

-- 
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v6 2/2] iommu/arm-smmu: add support for iova_to_phys through ATS1PR

2014-10-14 Thread Mitchel Humpherys
Currently, we provide the iommu_ops.iova_to_phys service by doing a
table walk in software to translate IO virtual addresses to physical
addresses. On SMMUs that support it, it can be useful to ask the SMMU
itself to do the translation. This can be used to warm the TLBs for an
SMMU. It can also be useful for testing and hardware validation.

Since the address translation registers are optional on SMMUv2, only
enable hardware translations when using SMMUv1 or when SMMU_IDR0.S1TS=1
and SMMU_IDR0.ATOSNS=0, as described in the ARM SMMU v1-v2 spec.

Signed-off-by: Mitchel Humpherys 
---
Changes since v5:
  - None. Re-sending series due to change in patch 1/2 in series
---
 drivers/iommu/arm-smmu.c | 79 +++-
 1 file changed, 78 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 37dc3dd0df..ef57043994 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -36,6 +36,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -140,6 +141,7 @@
 #define ID0_S2TS   (1 << 29)
 #define ID0_NTS(1 << 28)
 #define ID0_SMS(1 << 27)
+#define ID0_ATOSNS (1 << 26)
 #define ID0_PTFS_SHIFT 24
 #define ID0_PTFS_MASK  0x2
 #define ID0_PTFS_V8_ONLY   0x2
@@ -233,11 +235,16 @@
 #define ARM_SMMU_CB_TTBR0_HI   0x24
 #define ARM_SMMU_CB_TTBCR  0x30
 #define ARM_SMMU_CB_S1_MAIR0   0x38
+#define ARM_SMMU_CB_PAR_LO 0x50
+#define ARM_SMMU_CB_PAR_HI 0x54
 #define ARM_SMMU_CB_FSR0x58
 #define ARM_SMMU_CB_FAR_LO 0x60
 #define ARM_SMMU_CB_FAR_HI 0x64
 #define ARM_SMMU_CB_FSYNR0 0x68
 #define ARM_SMMU_CB_S1_TLBIASID0x610
+#define ARM_SMMU_CB_ATS1PR_LO  0x800
+#define ARM_SMMU_CB_ATS1PR_HI  0x804
+#define ARM_SMMU_CB_ATSR   0x8f0
 
 #define SCTLR_S1_ASIDPNE   (1 << 12)
 #define SCTLR_CFCFG(1 << 7)
@@ -249,6 +256,10 @@
 #define SCTLR_M(1 << 0)
 #define SCTLR_EAE_SBOP (SCTLR_AFE | SCTLR_TRE)
 
+#define CB_PAR_F   (1 << 0)
+
+#define ATSR_ACTIVE(1 << 0)
+
 #define RESUME_RETRY   (0 << 0)
 #define RESUME_TERMINATE   (1 << 0)
 
@@ -366,6 +377,7 @@ struct arm_smmu_device {
 #define ARM_SMMU_FEAT_TRANS_S1 (1 << 2)
 #define ARM_SMMU_FEAT_TRANS_S2 (1 << 3)
 #define ARM_SMMU_FEAT_TRANS_NESTED (1 << 4)
+#define ARM_SMMU_FEAT_TRANS_OPS(1 << 5)
u32 features;
 
 #define ARM_SMMU_OPT_SECURE_CFG_ACCESS (1 << 0)
@@ -1524,7 +1536,7 @@ static size_t arm_smmu_unmap(struct iommu_domain *domain, 
unsigned long iova,
return ret ? 0 : size;
 }
 
-static phys_addr_t arm_smmu_iova_to_phys(struct iommu_domain *domain,
+static phys_addr_t arm_smmu_iova_to_phys_soft(struct iommu_domain *domain,
 dma_addr_t iova)
 {
pgd_t *pgdp, pgd;
@@ -1557,6 +1569,66 @@ static phys_addr_t arm_smmu_iova_to_phys(struct 
iommu_domain *domain,
return __pfn_to_phys(pte_pfn(pte)) | (iova & ~PAGE_MASK);
 }
 
+static phys_addr_t arm_smmu_iova_to_phys_hard(struct iommu_domain *domain,
+   dma_addr_t iova)
+{
+   struct arm_smmu_domain *smmu_domain = domain->priv;
+   struct arm_smmu_device *smmu = smmu_domain->smmu;
+   struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
+   struct device *dev = smmu->dev;
+   void __iomem *cb_base;
+   u32 tmp;
+   u64 phys;
+   unsigned long flags;
+
+   cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx);
+
+   spin_lock_irqsave(&smmu_domain->lock, flags);
+
+   if (smmu->version == 1) {
+   u32 reg = iova & ~0xfff;
+   writel_relaxed(reg, cb_base + ARM_SMMU_CB_ATS1PR_LO);
+   } else {
+   u32 reg = iova & ~0xfff;
+   writel_relaxed(reg, cb_base + ARM_SMMU_CB_ATS1PR_LO);
+   reg = (iova & ~0xfff) >> 32;
+   writel_relaxed(reg, cb_base + ARM_SMMU_CB_ATS1PR_HI);
+   }
+
+   if (readl_poll_timeout_atomic(cb_base + ARM_SMMU_CB_ATSR, tmp,
+   !(tmp & ATSR_ACTIVE), 5, 50)) {
+   dev_err(dev,
+   "iova to phys timed out on 0x%pa. Falling back to 
software table walk.\n",
+   &iova);
+   return arm_smmu_iova_to_phys_soft(domain, iova);
+   }
+
+   phys = readl_relaxed(cb_base + ARM_SMMU_CB_PAR_LO);
+   phys |= ((u64) readl_relaxed(cb_base + ARM_SMMU_CB_PAR_HI)) << 32;
+
+   spin_unlock_irqrestore(&smmu_domain->lock, flags);
+
+   if (phys & CB_PAR_F) {
+   dev_err(dev, 

Re: [RFC PATCH v3 6/7] arm: call iommu_init before of_platform_populate

2014-10-14 Thread Laurent Pinchart
Hi Thierry,

On Tuesday 14 October 2014 17:05:29 Thierry Reding wrote:
> On Tue, Oct 14, 2014 at 06:01:58PM +0300, Laurent Pinchart wrote:
> > On Tuesday 14 October 2014 15:37:59 Thierry Reding wrote:
> >> On Tue, Oct 14, 2014 at 03:20:46PM +0200, Arnd Bergmann wrote:
> >>> On Tuesday 14 October 2014 16:07:38 Laurent Pinchart wrote:
>  On Tuesday 23 September 2014 09:44:25 Arnd Bergmann wrote:
> > On Tuesday 23 September 2014 09:02:39 Thierry Reding wrote:
> >>> I see two problems with using deferred probing here:
> >>> 
> >>> - we don't actually need to defer the probing but the binding to
> >>>   the driver when no dma ops are set, but it seems silly to even
> >>>   create the device before we can find out which ops it should
> >>>   use.
> >> 
> >> What does device creation have to do with anything? Surely a device
> >> won't need IOMMU services before the device is bound to a driver.
> > 
> > The problem is that the driver will start using the IOMMU as soon
> > as it calls dma_map_*, but that happens at runtime, not necessarily
> > during the probe function.
> > 
> > So we can get into the weird situation that probe() returns success,
> > but then you can't use the device yet because you don't know whether
> > it is supposed to use an IOMMU or not.
>  
>  If we want IOMMU devices to be supported by common device drivers we
>  need to defer probing of the master devices, there's no doubt about
>  that. Earlier approaches that hooked up into the device core code
>  were rejected, but it should be possible to use bus notifiers to
>  achieve the same result (with the drawback of having to register one
>  notifier per bus). The BUS_NOTIFY_BIND_DRIVER notifier can then just
>  return -EPROBE_DEFER when a iommus property is available and points to
>  an IOMMU not registered yet. I'm not saying we have to do this, but I
>  believe that at least from a technical point of view it could be done.
> >>> 
> >>> I think that fundamentally speaking, relying on notifiers for
> >>> something like this is very problematic, both in terms of
> >>> maintainability and reliability. We should really try to get the
> >>> notifiers out of the iommu handling, not put more of them in.
> >> 
> >> Agreed. Also last time I checked the driver core simply ignored the
> >> return value from notifiers, therefore this wouldn't work without
> >> changing the core either.
> >> 
> >> Still, I agree with Laurent that we really should be relying on probe
> >> deferral for probe ordering.
> > 
> > *If* we decide to support IOMMUs with real devices ;-)
> > 
> > I don't have a strong opinion on the subject. I initially thought it would
> > be a shame not to be able to use devres, until realizing that binding to
> > a DT node instead of a device meant that no unbind can ever occur.
> > Loosing dev_* support is also an annoyance though.
> 
> Binding to a DT node then also means that you can't build the driver as
> a module. And in particular for multiplatform kernels this is going to
> be a problem eventually.

It will, but other dependencies will make multiplatform kernels unpractical 
with or without IOMMUs anyway. Many platforms need clocks, timers, pin 
control, gpio, i2c and pmic support to boot to userspace. Agreed, that's not a 
valid reason to make the problem worse just for the sake of it.

-- 
Regards,

Laurent Pinchart

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [RFC PATCH v3 6/7] arm: call iommu_init before of_platform_populate

2014-10-14 Thread Thierry Reding
On Tue, Oct 14, 2014 at 06:01:58PM +0300, Laurent Pinchart wrote:
> Hi Thierry,
> 
> On Tuesday 14 October 2014 15:37:59 Thierry Reding wrote:
> > On Tue, Oct 14, 2014 at 03:20:46PM +0200, Arnd Bergmann wrote:
> > > On Tuesday 14 October 2014 16:07:38 Laurent Pinchart wrote:
> > >> On Tuesday 23 September 2014 09:44:25 Arnd Bergmann wrote:
> > >>> On Tuesday 23 September 2014 09:02:39 Thierry Reding wrote:
> > > I see two problems with using deferred probing here:
> > > 
> > > - we don't actually need to defer the probing but the binding to
> > >   the driver when no dma ops are set, but it seems silly to even
> > >   create the device before we can find out which ops it should use.
> >  
> >  What does device creation have to do with anything? Surely a device
> >  won't need IOMMU services before the device is bound to a driver.
> > >>> 
> > >>> The problem is that the driver will start using the IOMMU as soon
> > >>> as it calls dma_map_*, but that happens at runtime, not necessarily
> > >>> during the probe function.
> > >>> 
> > >>> So we can get into the weird situation that probe() returns success,
> > >>> but then you can't use the device yet because you don't know whether
> > >>> it is supposed to use an IOMMU or not.
> > >> 
> > >> If we want IOMMU devices to be supported by common device drivers we
> > >> need to defer probing of the master devices, there's no doubt about
> > >> that. Earlier approaches that hooked up into the device core code were
> > >> rejected, but it should be possible to use bus notifiers to achieve the
> > >> same result (with the drawback of having to register one notifier per
> > >> bus). The BUS_NOTIFY_BIND_DRIVER notifier can then just return -
> > >> EPROBE_DEFER when a iommus property is available and points to an IOMMU
> > >> not registered yet. I'm not saying we have to do this, but I believe that
> > >> at least from a technical point of view it could be done.
> > > 
> > > I think that fundamentally speaking, relying on notifiers for something
> > > like this is very problematic, both in terms of maintainability and
> > > reliability. We should really try to get the notifiers out of the iommu
> > > handling, not put more of them in.
> > 
> > Agreed. Also last time I checked the driver core simply ignored the
> > return value from notifiers, therefore this wouldn't work without
> > changing the core either.
> > 
> > Still, I agree with Laurent that we really should be relying on probe
> > deferral for probe ordering.
> 
> *If* we decide to support IOMMUs with real devices ;-)
> 
> I don't have a strong opinion on the subject. I initially thought it would be 
> a shame not to be able to use devres, until realizing that binding to a DT 
> node instead of a device meant that no unbind can ever occur. Loosing dev_* 
> support is also an annoyance though.

Binding to a DT node then also means that you can't build the driver as
a module. And in particular for multiplatform kernels this is going to
be a problem eventually.

Thierry


pgpXaYiR0yqh9.pgp
Description: PGP signature
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Re: [RFC PATCH v3 6/7] arm: call iommu_init before of_platform_populate

2014-10-14 Thread Laurent Pinchart
Hi Thierry,

On Tuesday 14 October 2014 15:37:59 Thierry Reding wrote:
> On Tue, Oct 14, 2014 at 03:20:46PM +0200, Arnd Bergmann wrote:
> > On Tuesday 14 October 2014 16:07:38 Laurent Pinchart wrote:
> >> On Tuesday 23 September 2014 09:44:25 Arnd Bergmann wrote:
> >>> On Tuesday 23 September 2014 09:02:39 Thierry Reding wrote:
> > I see two problems with using deferred probing here:
> > 
> > - we don't actually need to defer the probing but the binding to
> >   the driver when no dma ops are set, but it seems silly to even
> >   create the device before we can find out which ops it should use.
>  
>  What does device creation have to do with anything? Surely a device
>  won't need IOMMU services before the device is bound to a driver.
> >>> 
> >>> The problem is that the driver will start using the IOMMU as soon
> >>> as it calls dma_map_*, but that happens at runtime, not necessarily
> >>> during the probe function.
> >>> 
> >>> So we can get into the weird situation that probe() returns success,
> >>> but then you can't use the device yet because you don't know whether
> >>> it is supposed to use an IOMMU or not.
> >> 
> >> If we want IOMMU devices to be supported by common device drivers we
> >> need to defer probing of the master devices, there's no doubt about
> >> that. Earlier approaches that hooked up into the device core code were
> >> rejected, but it should be possible to use bus notifiers to achieve the
> >> same result (with the drawback of having to register one notifier per
> >> bus). The BUS_NOTIFY_BIND_DRIVER notifier can then just return -
> >> EPROBE_DEFER when a iommus property is available and points to an IOMMU
> >> not registered yet. I'm not saying we have to do this, but I believe that
> >> at least from a technical point of view it could be done.
> > 
> > I think that fundamentally speaking, relying on notifiers for something
> > like this is very problematic, both in terms of maintainability and
> > reliability. We should really try to get the notifiers out of the iommu
> > handling, not put more of them in.
> 
> Agreed. Also last time I checked the driver core simply ignored the
> return value from notifiers, therefore this wouldn't work without
> changing the core either.
> 
> Still, I agree with Laurent that we really should be relying on probe
> deferral for probe ordering.

*If* we decide to support IOMMUs with real devices ;-)

I don't have a strong opinion on the subject. I initially thought it would be 
a shame not to be able to use devres, until realizing that binding to a DT 
node instead of a device meant that no unbind can ever occur. Loosing dev_* 
support is also an annoyance though.

> And while it's true that earlier attempts to put this into the core were
> rejected, I think there's still value in proposing it again. The alternative
> proposed here is similarly close to the core and needs to duplicated for
> every architecture. That itself is to me a strong indication that this
> really does belong in the core.
> 
> I think initially this was proposed to become part of really_probe() and
> I still think that's where it belongs. There's precedent for it with the
> pinctrl_bind_pins() call, though it seems like Greg regrets allowing
> that into the core. Perhaps if really_probe() is "too core", then
> platform_drv_probe() would be a better candidate?

I've CC'ed Greg to this e-mail as he will likely have the last word on this 
topic.

-- 
Regards,

Laurent Pinchart

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [RFC PATCH v3 6/7] arm: call iommu_init before of_platform_populate

2014-10-14 Thread Thierry Reding
On Tue, Oct 14, 2014 at 03:20:46PM +0200, Arnd Bergmann wrote:
> On Tuesday 14 October 2014 16:07:38 Laurent Pinchart wrote:
> > On Tuesday 23 September 2014 09:44:25 Arnd Bergmann wrote:
> > > On Tuesday 23 September 2014 09:02:39 Thierry Reding wrote:
> > > > > I see two problems with using deferred probing here:
> > > > > 
> > > > > - we don't actually need to defer the probing but the binding to the
> > > > >   driver when no dma ops are set, but it seems silly to even create 
> > > > > the
> > > > >   device before we can find out which ops it should use.
> > > > 
> > > > What does device creation have to do with anything? Surely a device
> > > > won't need IOMMU services before the device is bound to a driver.
> > > 
> > > The problem is that the driver will start using the IOMMU as soon
> > > as it calls dma_map_*, but that happens at runtime, not necessarily
> > > during the probe function.
> > > 
> > > So we can get into the weird situation that probe() returns success,
> > > but then you can't use the device yet because you don't know whether
> > > it is supposed to use an IOMMU or not.
> > 
> > If we want IOMMU devices to be supported by common device drivers we need 
> > to 
> > defer probing of the master devices, there's no doubt about that. Earlier 
> > approaches that hooked up into the device core code were rejected, but it 
> > should be possible to use bus notifiers to achieve the same result (with 
> > the 
> > drawback of having to register one notifier per bus). The 
> > BUS_NOTIFY_BIND_DRIVER notifier can then just return -EPROBE_DEFER when a 
> > iommus property is available and points to an IOMMU not registered yet. I'm 
> > not saying we have to do this, but I believe that at least from a technical 
> > point of view it could be done.
> 
> I think that fundamentally speaking, relying on notifiers for something like
> this is very problematic, both in terms of maintainability and reliability.
> We should really try to get the notifiers out of the iommu handling, not put
> more of them in.

Agreed. Also last time I checked the driver core simply ignored the
return value from notifiers, therefore this wouldn't work without
changing the core either.

Still, I agree with Laurent that we really should be relying on probe
deferral for probe ordering. And while it's true that earlier attempts
to put this into the core were rejected, I think there's still value in
proposing it again. The alternative proposed here is similarly close to
the core and needs to duplicated for every architecture. That itself is
to me a strong indication that this really does belong in the core.

I think initially this was proposed to become part of really_probe() and
I still think that's where it belongs. There's precedent for it with the
pinctrl_bind_pins() call, though it seems like Greg regrets allowing
that into the core. Perhaps if really_probe() is "too core", then
platform_drv_probe() would be a better candidate?

Thierry


pgpgmTAxgroU9.pgp
Description: PGP signature
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Re: [RFC PATCH v3 6/7] arm: call iommu_init before of_platform_populate

2014-10-14 Thread Arnd Bergmann
On Tuesday 14 October 2014 16:07:38 Laurent Pinchart wrote:
> On Tuesday 23 September 2014 09:44:25 Arnd Bergmann wrote:
> > On Tuesday 23 September 2014 09:02:39 Thierry Reding wrote:
> > > > I see two problems with using deferred probing here:
> > > > 
> > > > - we don't actually need to defer the probing but the binding to the
> > > >   driver when no dma ops are set, but it seems silly to even create the
> > > >   device before we can find out which ops it should use.
> > > 
> > > What does device creation have to do with anything? Surely a device
> > > won't need IOMMU services before the device is bound to a driver.
> > 
> > The problem is that the driver will start using the IOMMU as soon
> > as it calls dma_map_*, but that happens at runtime, not necessarily
> > during the probe function.
> > 
> > So we can get into the weird situation that probe() returns success,
> > but then you can't use the device yet because you don't know whether
> > it is supposed to use an IOMMU or not.
> 
> If we want IOMMU devices to be supported by common device drivers we need to 
> defer probing of the master devices, there's no doubt about that. Earlier 
> approaches that hooked up into the device core code were rejected, but it 
> should be possible to use bus notifiers to achieve the same result (with the 
> drawback of having to register one notifier per bus). The 
> BUS_NOTIFY_BIND_DRIVER notifier can then just return -EPROBE_DEFER when a 
> iommus property is available and points to an IOMMU not registered yet. I'm 
> not saying we have to do this, but I believe that at least from a technical 
> point of view it could be done.

I think that fundamentally speaking, relying on notifiers for something like
this is very problematic, both in terms of maintainability and reliability.
We should really try to get the notifiers out of the iommu handling, not put
more of them in.

Arnd
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [RFC PATCH v3 4/7] iommu: provide helper function to configure an IOMMU for an of master

2014-10-14 Thread Laurent Pinchart
Hi Will,

On Monday 22 September 2014 18:13:52 Will Deacon wrote:
> On Thu, Sep 18, 2014 at 12:13:13PM +0100, Laurent Pinchart wrote:
> > Hi Will,
> 
> Hi Laurent,
> 
> > Thank you for the patch.
> 
> Sorry for the delay in replying, I was at Connect last week and the email
> has backed up.

No worries.

> > On Friday 12 September 2014 17:34:52 Will Deacon wrote:
> >> The generic IOMMU device-tree bindings can be used to add arbitrary OF
> >> masters to an IOMMU with a compliant binding.
> >> 
> >> This patch introduces of_iommu_configure, which does exactly that. A
> >> list of iommu_dma_mapping structures are created for each device, which
> >> represent the set of IOMMU instances through which the device can
> >> master. The list is protected by a kref count and freed when no users
> >> remain. It is expected that DMA-mapping code will take a reference if it
> >> wishes to make use of the IOMMU information.
> 
> [...]
> 
> >> +struct iommu_dma_mapping *of_iommu_configure(struct device *dev)
> >> +{
> >> +  struct of_phandle_args iommu_spec;
> >> +  struct iommu_dma_mapping *mapping;
> >> +  struct device_node *np;
> >> +  struct iommu_data *iommu = NULL;
> >> +  int idx = 0;
> >> +
> >> +  /*
> >> +   * We don't currently walk up the tree looking for a parent IOMMU.
> >> +   * See the `Notes:' section of
> >> +   * Documentation/devicetree/bindings/iommu/iommu.txt
> >> +   */
> >> +  while (!of_parse_phandle_with_args(dev->of_node, "iommus",
> >> + "#iommu-cells", idx,
> >> + &iommu_spec)) {
> >> +  struct iommu_data *data;
> >> +
> >> +  np = iommu_spec.np;
> >> +  data = of_iommu_get_data(np);
> >> +
> >> +  if (!data || !data->ops || !data->ops->of_xlate)
> >> +  goto err_put_node;
> >> +
> >> +  if (!iommu) {
> >> +  iommu = data;
> >> +  } else if (iommu != data) {
> >> +  /* We don't currently support multi-IOMMU masters */
> >> +  pr_warn("Rejecting device %s with multiple IOMMU 
instances\n",
> >> +  dev_name(dev));
> >> +  goto err_put_node;
> >> +  }
> >> +
> >> +  if (!data->ops->of_xlate(dev, &iommu_spec))
> >> +  goto err_put_node;
> >> +
> >> +  of_node_put(np);
> >> +  idx++;
> >> +  }
> >> +
> >> +  if (!iommu)
> >> +  return NULL;
> >> +
> >> +  mapping = kzalloc(sizeof(*mapping), GFP_KERNEL);
> >> +  if (!mapping)
> >> +  return NULL;
> >> +
> >> +  kref_init(&mapping->kref);
> >> +  INIT_LIST_HEAD(&mapping->node);
> > 
> > I might be missing something, but that doesn't seem to match the commit
> > message. This creates a single iommu_dma_mapping per device, where is the
> > list supposed to be populated ?
> 
> Right. I currently only populate the first node in the list, and the loop
> above barfs if we find multiple IOMMUs. I was hoping you'd add support for
> that later on, as you mentioned the need for this so I guess you can test it
> too?

I can, I was just puzzled by the mismatch between the code and commit message. 
As your patch series doesn't provide a complete end-to-end implementation it's 
not always easy to understand how you envision that implementation to work, 
and thus difficult to implement the required modifications to the IOMMU 
driver.

> >> +void of_iommu_deconfigure(struct kref *kref)
> >> +{
> >> +  struct iommu_dma_mapping *mapping, *curr, *next;
> >> +
> >> +  mapping = container_of(kref, struct iommu_dma_mapping, kref);
> >> +  list_for_each_entry_safe(curr, next, &mapping->node, node) {
> >> +  list_del(&curr->node);
> >> +  kfree(curr);
> >> +  }
> > 
> > Don't you need to also kfree(mapping) here ?
> 
> Yup, thanks.
> 
> >> +}
> >> +
> > 
> > Do you expect other users of of_iommu_deconfigure() than kref_put() ? If
> > not, how about exposing an of_iommu_put(struct iommu_dma_mapping *) that
> > would call kref_put() internally, and hiding of_iommu_deconfigure() ?
> 
> That's a good idea, I'll do that.
> 
> >>  void __init of_iommu_init(void)
> >>  {
> >>struct device_node *np;
> >> diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
> >> index 1e944e77d38d..e60e52d82db9 100644
> >> --- a/include/linux/dma-mapping.h
> >> +++ b/include/linux/dma-mapping.h
> >> @@ -62,6 +62,14 @@ struct dma_map_ops {
> >>int is_phys;
> >>  };
> >> 
> >> +struct iommu_data;
> >> +
> >> +struct iommu_dma_mapping {
> >> +  struct iommu_data *iommu;
> >> +  struct list_head node;
> >> +  struct kref kref;
> >> +};
> > 
> > Could you please document the structure with kerneldoc ?
> 
> Ok, I'll try!

-- 
Regards,

Laurent Pinchart

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [RFC PATCH v3 6/7] arm: call iommu_init before of_platform_populate

2014-10-14 Thread Laurent Pinchart
Hi Arnd,

On Tuesday 23 September 2014 09:44:25 Arnd Bergmann wrote:
> On Tuesday 23 September 2014 09:02:39 Thierry Reding wrote:
> > > I see two problems with using deferred probing here:
> > > 
> > > - we don't actually need to defer the probing but the binding to the
> > >   driver when no dma ops are set, but it seems silly to even create the
> > >   device before we can find out which ops it should use.
> > 
> > What does device creation have to do with anything? Surely a device
> > won't need IOMMU services before the device is bound to a driver.
> 
> The problem is that the driver will start using the IOMMU as soon
> as it calls dma_map_*, but that happens at runtime, not necessarily
> during the probe function.
> 
> So we can get into the weird situation that probe() returns success,
> but then you can't use the device yet because you don't know whether
> it is supposed to use an IOMMU or not.

If we want IOMMU devices to be supported by common device drivers we need to 
defer probing of the master devices, there's no doubt about that. Earlier 
approaches that hooked up into the device core code were rejected, but it 
should be possible to use bus notifiers to achieve the same result (with the 
drawback of having to register one notifier per bus). The 
BUS_NOTIFY_BIND_DRIVER notifier can then just return -EPROBE_DEFER when a 
iommus property is available and points to an IOMMU not registered yet. I'm 
not saying we have to do this, but I believe that at least from a technical 
point of view it could be done.

> > >   The reason is that a driver does not actively ask for an IOMMU as it
> > >   would for other subsystems (gpio, led, dmaengine, ...).
> > 
> > Actually it does. At least in some cases. If you want to use the IOMMU
> > API directly you'd call something like iommu_present() on the bus type
> > and then allocate an IOMMU domain and attach to it. Unfortunately the
> > API seems to have been designed under the assumption that IOMMU will
> > have been registered before any users, so the API doesn't propagate any
> > meaningful errors.
> 
> That's just a special case that does not even work as it should yet,
> please don't confuse the matter more by talking about drivers that
> use the IOMMU API explicitly, this series has very little to do with
> that.
> 
> > Also, even if in other cases the drivers don't actively ask for an IOMMU
> > that doesn't mean that they couldn't be made to. For drivers that use
> > the DMA/IOMMU integration layer this is probably not practicable, but
> > there is no reason the core couldn't do it.
> 
> We intentionally have an abstraction that is meant to let you write drivers
> without knowing about iommu, swiotlb or coherency, these are all hidden
> behind the dma_map_ops implementation.

-- 
Regards,

Laurent Pinchart

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [RFC PATCH v3 5/7] dma-mapping: detect and configure IOMMU in of_dma_configure

2014-10-14 Thread Laurent Pinchart
Hi Will,

On Monday 22 September 2014 18:50:27 Will Deacon wrote:
> On Mon, Sep 22, 2014 at 10:29:10AM +0100, Thierry Reding wrote:
> > On Thu, Sep 18, 2014 at 02:17:33PM +0300, Laurent Pinchart wrote:
> >> On Friday 12 September 2014 17:34:53 Will Deacon wrote:
> >>> This patch extends of_dma_configure so that it sets up the IOMMU for a
> >>> device, as well as the coherent/non-coherent DMA mapping ops.
> >>> 
> >>> Signed-off-by: Will Deacon 
> >>> ---
> >>> 
> >>>  arch/arm/include/asm/dma-mapping.h |  4 +++-
> >>>  drivers/of/platform.c  | 24 +---
> >>>  include/linux/dma-mapping.h|  8 +++-
> >>>  3 files changed, 27 insertions(+), 9 deletions(-)
> >>> 
> >>> diff --git a/arch/arm/include/asm/dma-mapping.h
> >>> b/arch/arm/include/asm/dma-mapping.h index 7e9ac4f604c3..a8bb0c494bb3
> >>> 100644
> >>> --- a/arch/arm/include/asm/dma-mapping.h
> >>> +++ b/arch/arm/include/asm/dma-mapping.h
> >>> @@ -121,7 +121,9 @@ static inline unsigned long dma_max_pfn(struct
> >>> device *dev)
> >>>  }
> >>>  #define dma_max_pfn(dev) dma_max_pfn(dev)
> >>> 
> >>> -static inline void arch_setup_dma_ops(struct device *dev, bool
> >>> coherent)
> >>> +static inline void arch_setup_dma_ops(struct device *dev, u64
> >>> dma_base,
> >>> +   u64 size, struct iommu_dma_mapping *iommu,
> >>> +   bool coherent)
> >>>  {
> >>>   if (coherent)
> >>>   set_dma_ops(dev, &arm_coherent_dma_ops);
> >>> diff --git a/drivers/of/platform.c b/drivers/of/platform.c
> >>> index 946dd7ae0394..95ebd38db545 100644
> >>> --- a/drivers/of/platform.c
> >>> +++ b/drivers/of/platform.c
> >>> @@ -19,6 +19,7 @@
> >>>  #include 
> >>>  #include 
> >>>  #include 
> >>> +#include 
> >>>  #include 
> >>>  #include 
> >>>  #include 
> >>> @@ -166,6 +167,7 @@ static void of_dma_configure(struct
> >>> platform_device *pdev)
> >>>   int ret;
> >>>   bool coherent;
> >>>   unsigned long offset;
> >>> + struct iommu_dma_mapping *iommu;
> >>>   struct device *dev = &pdev->dev;
> >>>   
> >>>   /*
> >>> @@ -195,7 +197,19 @@ static void of_dma_configure(struct
> >>> platform_device *pdev)
> >>>   dev_dbg(dev, "device is%sdma coherent\n",
> >>>   coherent ? " " : " not ");
> >>> 
> >>> - arch_setup_dma_ops(dev, coherent);
> >>> + iommu = of_iommu_configure(dev);
> >>> + dev_dbg(dev, "device is%sbehind an iommu\n",
> >>> + iommu ? " " : " not ");
> >>> +
> >>> + arch_setup_dma_ops(dev, dma_addr, size, iommu, coherent);
> >>> +
> >>> + if (iommu)
> >>> + kref_put(&iommu->kref, of_iommu_deconfigure);
> >> 
> >> What's the expected life cycle of the iommu_dma_mapping structure ? It
> >> gets created by of_iommu_configure() and the initial reference gets
> >> dropped here. I suppose you expect arch code to need to keep a reference
> >> to the structure, but your implementation in patch 7/7 doesn't. As far as
> >> I can see, you don't even use the contents of the structure in the ARM
> >> arch_setup_dma_ops() implementation. Do you expect that to change later,
> >> or other architectures to need it ?
> >> 
> >> By the way, now that I think about it, I find struct iommu_dma_mapping
> >> and struct dma_iommu_mapping very confusing.
> > 
> > Agreed. I wonder how useful it is to know the set of IOMMU instances
> > that each device can master through. Wouldn't it be more useful to keep
> > a list of master interfaces for each device? The set of IOMMU instances
> > can trivially be derived from that.
> 
> I'm struggling to think how that would look. What do you mean by `master
> interfaces' in terms of the code we have in Linux? At the end of the day,
> the list of IOMMU instances (i.e. iommu_dma_mapping) exists because you
> and Laurent have use-cases involving devices mastering through multiple
> IOMMUs. If it doesn't work for you, it might be best for you to send me
> the patch ;)

Just for the record, I've brought up the topic of masters being served by 
multiple IOMMUs, but don't have a use case for it (yet at least). I do have 
masters served through multiple streams with separate stream IDs, but all by 
the same IOMMU.

-- 
Regards,

Laurent Pinchart

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[git pull] IOMMU Updates for Linux v3.18

2014-10-14 Thread Joerg Roedel
Hi Linus,

The following changes since commit fe82dcec644244676d55a1384c958d5f67979adb:

  Linux 3.17-rc7 (2014-09-28 14:29:07 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git 
tags/iommu-updates-v3.18

for you to fetch changes up to 09b5269a1b3d47525d7c25efeb16f5407ef82ea2:

  Merge branches 'arm/exynos', 'arm/omap', 'arm/smmu', 'x86/vt-d', 'x86/amd' 
and 'core' into next (2014-10-02 12:24:45 +0200)



IOMMU Updates for Linux v3.18

This pull-request includes:

* Change in the IOMMU-API to convert the former iommu_domain_capable
  function to just iommu_capable

* Various fixes in handling RMRR ranges for the VT-d driver (one fix
  requires a device driver core change which was acked
  by Greg KH)

* The AMD IOMMU driver now assigns and deassigns complete alias groups
  to fix issues with devices using the wrong PCI request-id

* MMU-401 support for the ARM SMMU driver

* Multi-master IOMMU group support for the ARM SMMU driver

* Various other small fixes all over the place


Alex Williamson (2):
  iommu: Rework iommu_group_get_for_pci_dev()
  iommu/amd: Split init_iommu_group() from iommu_init_device()

Andreea-Cristina Bernat (1):
  iommu: Replace rcu_assign_pointer() with RCU_INIT_POINTER()

Jan Kiszka (1):
  iommu/vt-d: Don't store SIRTP request

Joerg Roedel (23):
  iommu/amd: Move struct iommu_dev_data to amd_iommu.c
  iommu/amd: Keep a list of devices in an alias group
  iommu/amd: Attach and detach complete alias group
  iommu/amd: Remove device binding reference count
  Merge branch 'for-joerg/arm-smmu/updates' of 
git://git.kernel.org/.../will/linux into arm/smmu
  iommu: Convert iommu-caps from define to enum
  iommu: Introduce iommu_capable API function
  iommu/amd: Convert to iommu_capable() API function
  iommu/arm-smmu: Convert to iommu_capable() API function
  iommu/fsl: Convert to iommu_capable() API function
  iommu/vt-d: Convert to iommu_capable() API function
  iommu/msm: Convert to iommu_capable() API function
  iommu/tegra: Convert to iommu_capable() API function
  kvm: iommu: Convert to use new iommu_capable() API function
  vfio: Convert to use new iommu_capable() API function
  IB/usnic: Convert to use new iommu_capable() API function
  iommu: Remove iommu_domain_has_cap() API function
  iommu/amd: Fix devid mapping for ivrs_ioapic override
  driver core: Add BUS_NOTIFY_REMOVED_DEVICE event
  iommu/vt-d: Only remove domain when device is removed
  iommu/vt-d: Store bus information in RMRR PCI device path
  iommu/vt-d: Work around broken RMRR firmware entries
  Merge branches 'arm/exynos', 'arm/omap', 'arm/smmu', 'x86/vt-d', 
'x86/amd' and 'core' into next

Kiran Padwal (1):
  iommu: Make of_device_id array const

Laurent Pinchart (1):
  iommu/omap: Remove omap_iommu unused owner field

Mark Salter (1):
  iommu: Fix bus notifier breakage

Maurizio Lombardi (1):
  amd_iommu: do not dereference a NULL pointer address.

Mitchel Humpherys (1):
  iommu/arm-smmu: fix bug in pmd construction

Robin Murphy (2):
  iommu/arm-smmu: fix architecture version detection
  iommu/arm-smmu: support MMU-401

Sachin Kamat (1):
  iommu/exynos: Fix trivial typos

Suman Anna (2):
  iommu/omap: Check for valid archdata in attach_dev
  iommu/omap: Fix iommu archdata name for DT-based devices

Will Deacon (5):
  iommu/arm-smmu: allow translation stage to be forced on the cmdline
  iommu/arm-smmu: add support for multi-master iommu groups
  iommu/arm-smmu: put iommu_domain pointer in dev->archdata.iommu
  iommu/arm-smmu: use page shift instead of page size to avoid division
  iommu/arm-smmu: don't bother truncating the s1 output size to VA_BITS

Yijing Wang (1):
  iommu/irq_remapping: Fix the regression of hpet irq remapping

 .../devicetree/bindings/iommu/arm,smmu.txt |   1 +
 drivers/base/core.c|   3 +
 drivers/infiniband/hw/usnic/usnic_uiom.c   |   2 +-
 drivers/iommu/amd_iommu.c  | 117 ++-
 drivers/iommu/amd_iommu_init.c |  21 +-
 drivers/iommu/amd_iommu_types.h|  21 --
 drivers/iommu/arm-smmu.c   | 220 -
 drivers/iommu/dmar.c   |  25 ++-
 drivers/iommu/exynos-iommu.c   |  51 ++---
 drivers/iommu/fsl_pamu_domain.c|   5 +-
 drivers/iommu/intel-iommu.c|  16 +-
 drivers/iommu/intel_irq_remapping.c|   7 +-
 drivers/iommu/iommu.c  | 208 +++
 drivers/iommu/irq_rema

[PATCH v5 1/3] iommu/rockchip: rk3288 iommu driver

2014-10-14 Thread Daniel Kurtz
The rk3288 has several iommus.  Each iommu belongs to a single master
device.  There is one device (ISP) that has two slave iommus, but that
case is not yet supported by this driver.

At subsys init, the iommu driver registers itself as the iommu driver for
the platform bus.  The master devices find their slave iommus using the
"iommus" field in their devicetree description.  Since each slave iommu
belongs to exactly one master, their is no additional data needed at probe
to associate a slave with its master.

An iommu device's power domain, clock and irq are all shared with its
master device, and the master device must be careful to attach from the
iommu only after powering and clocking it (and leave it powered and
clocked before detaching).  Because their is no guarantee what the status
of the iommu is at probe, and since the driver does not even know if the
device is powered, we delay requesting its irq until the master device
attaches, at which point we have a guarantee that the device is powered
and clocked and we can reset it and disable its interrupt mask.

An iommu_domain describes a virtual iova address space.  Each iommu_domain
has a corresponding page table that lists the mappings from iova to
physical address.

For the rk3288 iommu, the page table has two levels:
 The Level 1 "directory_table" has 1024 4-byte dte entries.
 Each dte points to a level 2 "page_table".
 Each level 2 page_table has 1024 4-byte pte entries.
 Each pte points to a 4 KiB page of memory.

An iommu_domain is created when a dma_iommu_mapping is created via
arm_iommu_create_mapping.  Master devices can then attach themselves to
this mapping (or attach the mapping to themselves?) by calling
arm_iommu_attach_device().  This in turn instructs the iommu driver to
write the page table's physical address into the slave iommu's "Directory
Table Entry" (DTE) register.

In fact multiple master devices, each with their own slave iommu device,
can all attach to the same mapping.  The iommus for these devices will
share the same iommu_domain and therefore point to the same page table.
Thus, the iommu domain maintains a list of iommu devices which are
attached.  This driver relies on the iommu core to ensure that all devices
have detached before destroying a domain.

Signed-off-by: Daniel Kurtz 
Signed-off-by: Simon Xue 
Reviewed-by: Grant Grundler 
Reviewed-by: Stéphane Marchesin 
---
 drivers/iommu/Kconfig  |  12 +
 drivers/iommu/Makefile |   1 +
 drivers/iommu/rockchip-iommu.c | 924 +
 3 files changed, 937 insertions(+)
 create mode 100644 drivers/iommu/rockchip-iommu.c

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index dd51122..d0a1261 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -152,6 +152,18 @@ config OMAP_IOMMU_DEBUG
 
  Say N unless you know you need this.
 
+config ROCKCHIP_IOMMU
+   bool "Rockchip IOMMU Support"
+   depends on ARCH_ROCKCHIP
+   select IOMMU_API
+   select ARM_DMA_USE_IOMMU
+   help
+ Support for IOMMUs found on Rockchip rk32xx SOCs.
+ These IOMMUs allow virtualization of the address space used by most
+ cores within the multimedia subsystem.
+ Say Y here if you are using a Rockchip SoC that includes an IOMMU
+ device.
+
 config TEGRA_IOMMU_GART
bool "Tegra GART IOMMU Support"
depends on ARCH_TEGRA_2x_SOC
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index 16edef7..3e47ef3 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o 
irq_remapping.o
 obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o
 obj-$(CONFIG_OMAP_IOMMU) += omap-iommu2.o
 obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o
+obj-$(CONFIG_ROCKCHIP_IOMMU) += rockchip-iommu.o
 obj-$(CONFIG_TEGRA_IOMMU_GART) += tegra-gart.o
 obj-$(CONFIG_TEGRA_IOMMU_SMMU) += tegra-smmu.o
 obj-$(CONFIG_EXYNOS_IOMMU) += exynos-iommu.o
diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
new file mode 100644
index 000..08e50fc
--- /dev/null
+++ b/drivers/iommu/rockchip-iommu.c
@@ -0,0 +1,924 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/** MMU register offsets */
+#define RK_MMU_DTE_ADDR0x00/* Directory table address */
+#define RK_MMU_STATUS  0x04
+#define RK_MMU_COMMAND 0x08
+#define RK_MMU_PAGE_FAULT_ADDR 0x0C/* IOVA of last page fault */
+#define RK_MMU_ZAP_ONE_LINE0x10/* Shootdown one IOTLB entry */
+#define RK_MMU_INT_RAWSTAT 0x14/* IRQ status ignoring mask */
+#define RK_MMU_INT_CLEA

[PATCH v4 1/3] iommu/rockchip: rk3288 iommu driver

2014-10-14 Thread Daniel Kurtz
The rk3288 has several iommus.  Each iommu belongs to a single master
device.  There is one device (ISP) that has two slave iommus, but that
case is not yet supported by this driver.

At subsys init, the iommu driver registers itself as the iommu driver for
the platform bus.  The master devices find their slave iommus using the
"iommus" field in their devicetree description.  Since each slave iommu
belongs to exactly one master, their is no additional data needed at probe
to associate a slave with its master.

An iommu device's power domain, clock and irq are all shared with its
master device, and the master device must be careful to attach from the
iommu only after powering and clocking it (and leave it powered and
clocked before detaching).  Because their is no guarantee what the status
of the iommu is at probe, and since the driver does not even know if the
device is powered, we delay requesting its irq until the master device
attaches, at which point we have a guarantee that the device is powered
and clocked and we can reset it and disable its interrupt mask.

An iommu_domain describes a virtual iova address space.  Each iommu_domain
has a corresponding page table that lists the mappings from iova to
physical address.

For the rk3288 iommu, the page table has two levels:
 The Level 1 "directory_table" has 1024 4-byte dte entries.
 Each dte points to a level 2 "page_table".
 Each level 2 page_table has 1024 4-byte pte entries.
 Each pte points to a 4 KiB page of memory.

An iommu_domain is created when a dma_iommu_mapping is created via
arm_iommu_create_mapping.  Master devices can then attach themselves to
this mapping (or attach the mapping to themselves?) by calling
arm_iommu_attach_device().  This in turn instructs the iommu driver to
write the page table's physical address into the slave iommu's "Directory
Table Entry" (DTE) register.

In fact multiple master devices, each with their own slave iommu device,
can all attach to the same mapping.  The iommus for these devices will
share the same iommu_domain and therefore point to the same page table.
Thus, the iommu domain maintains a list of iommu devices which are
attached.  This driver relies on the iommu core to ensure that all devices
have detached before destroying a domain.

Signed-off-by: Daniel Kurtz 
Signed-off-by: Simon Xue 
Reviewed-by: Grant Grundler 
Reviewed-by: Stéphane Marchesin 
---
 drivers/iommu/Kconfig  |  12 +
 drivers/iommu/Makefile |   1 +
 drivers/iommu/rockchip-iommu.c | 924 +
 3 files changed, 937 insertions(+)
 create mode 100644 drivers/iommu/rockchip-iommu.c

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index dd51122..d0a1261 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -152,6 +152,18 @@ config OMAP_IOMMU_DEBUG
 
  Say N unless you know you need this.
 
+config ROCKCHIP_IOMMU
+   bool "Rockchip IOMMU Support"
+   depends on ARCH_ROCKCHIP
+   select IOMMU_API
+   select ARM_DMA_USE_IOMMU
+   help
+ Support for IOMMUs found on Rockchip rk32xx SOCs.
+ These IOMMUs allow virtualization of the address space used by most
+ cores within the multimedia subsystem.
+ Say Y here if you are using a Rockchip SoC that includes an IOMMU
+ device.
+
 config TEGRA_IOMMU_GART
bool "Tegra GART IOMMU Support"
depends on ARCH_TEGRA_2x_SOC
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index 16edef7..3e47ef3 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o 
irq_remapping.o
 obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o
 obj-$(CONFIG_OMAP_IOMMU) += omap-iommu2.o
 obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o
+obj-$(CONFIG_ROCKCHIP_IOMMU) += rockchip-iommu.o
 obj-$(CONFIG_TEGRA_IOMMU_GART) += tegra-gart.o
 obj-$(CONFIG_TEGRA_IOMMU_SMMU) += tegra-smmu.o
 obj-$(CONFIG_EXYNOS_IOMMU) += exynos-iommu.o
diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
new file mode 100644
index 000..08e50fc
--- /dev/null
+++ b/drivers/iommu/rockchip-iommu.c
@@ -0,0 +1,924 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/** MMU register offsets */
+#define RK_MMU_DTE_ADDR0x00/* Directory table address */
+#define RK_MMU_STATUS  0x04
+#define RK_MMU_COMMAND 0x08
+#define RK_MMU_PAGE_FAULT_ADDR 0x0C/* IOVA of last page fault */
+#define RK_MMU_ZAP_ONE_LINE0x10/* Shootdown one IOTLB entry */
+#define RK_MMU_INT_RAWSTAT 0x14/* IRQ status ignoring mask */
+#define RK_MMU_INT_CLEA