genirq/msi: Allow creation of a tree-based irqdomain for platform-msi
authorMarc Zyngier <marc.zyngier@arm.com>
Mon, 1 Oct 2018 14:13:45 +0000 (16:13 +0200)
committerMarc Zyngier <marc.zyngier@arm.com>
Tue, 2 Oct 2018 10:16:38 +0000 (11:16 +0100)
platform_msi_create_device_domain() always creates a revmap-based
irqdomain, which has the drawback of requiring the number of MSIs
that can be allocated ahead of time. This is not always possible,
and we sometimes need to use a tree-based irqdomain instead.

Add a new platform_msi_create_device_tree_domain() helper to
that effect.

Reported-by: Miquel Raynal <miquel.raynal@bootlin.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
drivers/base/platform-msi.c
include/linux/msi.h

index 60d6cc6..f39a920 100644 (file)
@@ -321,11 +321,12 @@ void *platform_msi_get_host_data(struct irq_domain *domain)
  * Returns an irqdomain for @nvec interrupts
  */
 struct irq_domain *
-platform_msi_create_device_domain(struct device *dev,
-                                 unsigned int nvec,
-                                 irq_write_msi_msg_t write_msi_msg,
-                                 const struct irq_domain_ops *ops,
-                                 void *host_data)
+__platform_msi_create_device_domain(struct device *dev,
+                                   unsigned int nvec,
+                                   bool is_tree,
+                                   irq_write_msi_msg_t write_msi_msg,
+                                   const struct irq_domain_ops *ops,
+                                   void *host_data)
 {
        struct platform_msi_priv_data *data;
        struct irq_domain *domain;
@@ -336,7 +337,8 @@ platform_msi_create_device_domain(struct device *dev,
                return NULL;
 
        data->host_data = host_data;
-       domain = irq_domain_create_hierarchy(dev->msi_domain, 0, nvec,
+       domain = irq_domain_create_hierarchy(dev->msi_domain, 0,
+                                            is_tree ? 0 : nvec,
                                             dev->fwnode, ops, data);
        if (!domain)
                goto free_priv;
index 5839d80..0e9c500 100644 (file)
@@ -317,11 +317,18 @@ int msi_domain_prepare_irqs(struct irq_domain *domain, struct device *dev,
 int msi_domain_populate_irqs(struct irq_domain *domain, struct device *dev,
                             int virq, int nvec, msi_alloc_info_t *args);
 struct irq_domain *
-platform_msi_create_device_domain(struct device *dev,
-                                 unsigned int nvec,
-                                 irq_write_msi_msg_t write_msi_msg,
-                                 const struct irq_domain_ops *ops,
-                                 void *host_data);
+__platform_msi_create_device_domain(struct device *dev,
+                                   unsigned int nvec,
+                                   bool is_tree,
+                                   irq_write_msi_msg_t write_msi_msg,
+                                   const struct irq_domain_ops *ops,
+                                   void *host_data);
+
+#define platform_msi_create_device_domain(dev, nvec, write, ops, data) \
+       __platform_msi_create_device_domain(dev, nvec, false, write, ops, data)
+#define platform_msi_create_device_tree_domain(dev, nvec, write, ops, data) \
+       __platform_msi_create_device_domain(dev, nvec, true, write, ops, data)
+
 int platform_msi_domain_alloc(struct irq_domain *domain, unsigned int virq,
                              unsigned int nr_irqs);
 void platform_msi_domain_free(struct irq_domain *domain, unsigned int virq,