irqdomain: Simplify simple and legacy domain creation

irq_domain_create_simple() and irq_domain_create_legacy() use
__irq_domain_instantiate(), but have extra handling of allocating interrupt
descriptors and associating interrupts in them. Some of that is duplicated.

There are also call sites which have conditonals to invoke different
interrupt domain creator functions, where one of them is usually
irq_domain_create_legacy(). Alternatively they associate the interrupts for
the legacy case after creating the domain.

Moving the extra logic of irq_domain_create_simple()/legacy() into
__irq_domain_instantiate() allows to consolidate that.

Introduce hwirq_base and virq_base members in the irq_domain_info
structure, which allows to transport the required information and add the
conditional interrupt descriptor allocation and interrupt association into
__irq_domain_instantiate().

This reduces irq_domain_create_legacy() and irq_domain_create_simple() to
trivial wrappers which fill in the info structure and allows call sites
which must support the legacy case along with more modern mechanism to
select the domain type via the parameters of the info struct.

[ tglx: Massaged change log ]

Suggested-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Matti Vaittinen <mazziesaccount@gmail.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/all/32d07bd79eb2b5416e24da9e9e8fe5955423dcf9.1723120028.git.mazziesaccount@gmail.com
This commit is contained in:
Matti Vaittinen 2024-08-08 15:34:02 +03:00 committed by Thomas Gleixner
parent 8400291e28
commit 70114e7f75
2 changed files with 46 additions and 33 deletions

View File

@ -291,6 +291,9 @@ struct irq_domain_chip_generic_info;
* @hwirq_max: Maximum number of interrupts supported by controller
* @direct_max: Maximum value of direct maps;
* Use ~0 for no limit; 0 for no direct mapping
* @hwirq_base: The first hardware interrupt number (legacy domains only)
* @virq_base: The first Linux interrupt number for legacy domains to
* immediately associate the interrupts after domain creation
* @bus_token: Domain bus token
* @ops: Domain operation callbacks
* @host_data: Controller private data pointer
@ -307,6 +310,8 @@ struct irq_domain_info {
unsigned int size;
irq_hw_number_t hwirq_max;
int direct_max;
unsigned int hwirq_base;
unsigned int virq_base;
enum irq_domain_bus_token bus_token;
const struct irq_domain_ops *ops;
void *host_data;

View File

@ -267,13 +267,20 @@ static void irq_domain_free(struct irq_domain *domain)
kfree(domain);
}
/**
* irq_domain_instantiate() - Instantiate a new irq domain data structure
* @info: Domain information pointer pointing to the information for this domain
*
* Return: A pointer to the instantiated irq domain or an ERR_PTR value.
*/
struct irq_domain *irq_domain_instantiate(const struct irq_domain_info *info)
static void irq_domain_instantiate_descs(const struct irq_domain_info *info)
{
if (!IS_ENABLED(CONFIG_SPARSE_IRQ))
return;
if (irq_alloc_descs(info->virq_base, info->virq_base, info->size,
of_node_to_nid(to_of_node(info->fwnode))) < 0) {
pr_info("Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n",
info->virq_base);
}
}
static struct irq_domain *__irq_domain_instantiate(const struct irq_domain_info *info,
bool cond_alloc_descs)
{
struct irq_domain *domain;
int err;
@ -306,6 +313,15 @@ struct irq_domain *irq_domain_instantiate(const struct irq_domain_info *info)
__irq_domain_publish(domain);
if (cond_alloc_descs && info->virq_base > 0)
irq_domain_instantiate_descs(info);
/* Legacy interrupt domains have a fixed Linux interrupt number */
if (info->virq_base > 0) {
irq_domain_associate_many(domain, info->virq_base, info->hwirq_base,
info->size - info->hwirq_base);
}
return domain;
err_domain_gc_remove:
@ -315,6 +331,17 @@ err_domain_free:
irq_domain_free(domain);
return ERR_PTR(err);
}
/**
* irq_domain_instantiate() - Instantiate a new irq domain data structure
* @info: Domain information pointer pointing to the information for this domain
*
* Return: A pointer to the instantiated irq domain or an ERR_PTR value.
*/
struct irq_domain *irq_domain_instantiate(const struct irq_domain_info *info)
{
return __irq_domain_instantiate(info, false);
}
EXPORT_SYMBOL_GPL(irq_domain_instantiate);
/**
@ -413,28 +440,13 @@ struct irq_domain *irq_domain_create_simple(struct fwnode_handle *fwnode,
.fwnode = fwnode,
.size = size,
.hwirq_max = size,
.virq_base = first_irq,
.ops = ops,
.host_data = host_data,
};
struct irq_domain *domain;
struct irq_domain *domain = __irq_domain_instantiate(&info, true);
domain = irq_domain_instantiate(&info);
if (IS_ERR(domain))
return NULL;
if (first_irq > 0) {
if (IS_ENABLED(CONFIG_SPARSE_IRQ)) {
/* attempt to allocated irq_descs */
int rc = irq_alloc_descs(first_irq, first_irq, size,
of_node_to_nid(to_of_node(fwnode)));
if (rc < 0)
pr_info("Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n",
first_irq);
}
irq_domain_associate_many(domain, first_irq, 0, size);
}
return domain;
return IS_ERR(domain) ? NULL : domain;
}
EXPORT_SYMBOL_GPL(irq_domain_create_simple);
@ -476,18 +488,14 @@ struct irq_domain *irq_domain_create_legacy(struct fwnode_handle *fwnode,
.fwnode = fwnode,
.size = first_hwirq + size,
.hwirq_max = first_hwirq + size,
.hwirq_base = first_hwirq,
.virq_base = first_irq,
.ops = ops,
.host_data = host_data,
};
struct irq_domain *domain;
struct irq_domain *domain = irq_domain_instantiate(&info);
domain = irq_domain_instantiate(&info);
if (IS_ERR(domain))
return NULL;
irq_domain_associate_many(domain, first_irq, first_hwirq, size);
return domain;
return IS_ERR(domain) ? NULL : domain;
}
EXPORT_SYMBOL_GPL(irq_domain_create_legacy);