Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

genirq/msi: Allow creation of a tree-based irqdomain for platform-msi

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>

+20 -11
+8 -6
drivers/base/platform-msi.c
··· 321 321 * Returns an irqdomain for @nvec interrupts 322 322 */ 323 323 struct irq_domain * 324 - platform_msi_create_device_domain(struct device *dev, 325 - unsigned int nvec, 326 - irq_write_msi_msg_t write_msi_msg, 327 - const struct irq_domain_ops *ops, 328 - void *host_data) 324 + __platform_msi_create_device_domain(struct device *dev, 325 + unsigned int nvec, 326 + bool is_tree, 327 + irq_write_msi_msg_t write_msi_msg, 328 + const struct irq_domain_ops *ops, 329 + void *host_data) 329 330 { 330 331 struct platform_msi_priv_data *data; 331 332 struct irq_domain *domain; ··· 337 336 return NULL; 338 337 339 338 data->host_data = host_data; 340 - domain = irq_domain_create_hierarchy(dev->msi_domain, 0, nvec, 339 + domain = irq_domain_create_hierarchy(dev->msi_domain, 0, 340 + is_tree ? 0 : nvec, 341 341 dev->fwnode, ops, data); 342 342 if (!domain) 343 343 goto free_priv;
+12 -5
include/linux/msi.h
··· 317 317 int msi_domain_populate_irqs(struct irq_domain *domain, struct device *dev, 318 318 int virq, int nvec, msi_alloc_info_t *args); 319 319 struct irq_domain * 320 - platform_msi_create_device_domain(struct device *dev, 321 - unsigned int nvec, 322 - irq_write_msi_msg_t write_msi_msg, 323 - const struct irq_domain_ops *ops, 324 - void *host_data); 320 + __platform_msi_create_device_domain(struct device *dev, 321 + unsigned int nvec, 322 + bool is_tree, 323 + irq_write_msi_msg_t write_msi_msg, 324 + const struct irq_domain_ops *ops, 325 + void *host_data); 326 + 327 + #define platform_msi_create_device_domain(dev, nvec, write, ops, data) \ 328 + __platform_msi_create_device_domain(dev, nvec, false, write, ops, data) 329 + #define platform_msi_create_device_tree_domain(dev, nvec, write, ops, data) \ 330 + __platform_msi_create_device_domain(dev, nvec, true, write, ops, data) 331 + 325 332 int platform_msi_domain_alloc(struct irq_domain *domain, unsigned int virq, 326 333 unsigned int nr_irqs); 327 334 void platform_msi_domain_free(struct irq_domain *domain, unsigned int virq,