irqdomain: Add a fwnode_handle allocator
In order to be able to reference an irqdomain from ACPI, we need to be able to create an identifier, which is usually a struct device_node. This device node does't really fit the ACPI infrastructure, so we cunningly allocate a new structure containing a fwnode_handle, and return that. This structure doesn't really point to a device (interrupt controllers are not "real" devices in Linux), but as we cannot really deny that they exist, we create them with a new fwnode_type (FWNODE_IRQCHIP). Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Reviewed-and-tested-by: Hanjun Guo <hanjun.guo@linaro.org> Tested-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> Cc: <linux-arm-kernel@lists.infradead.org> Cc: Tomasz Nowicki <tomasz.nowicki@linaro.org> Cc: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com> Cc: Graeme Gregory <graeme@xora.org.uk> Cc: Jake Oshins <jakeo@microsoft.com> Cc: Jiang Liu <jiang.liu@linux.intel.com> Cc: Jason Cooper <jason@lakedaemon.net> Cc: Rafael J. Wysocki <rjw@rjwysocki.net> Link: http://lkml.kernel.org/r/1444737105-31573-9-git-send-email-marc.zyngier@arm.com Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
committed by
Thomas Gleixner
parent
1bf4ddc46c
commit
b145dcc45a
@@ -17,6 +17,7 @@ enum fwnode_type {
|
|||||||
FWNODE_OF,
|
FWNODE_OF,
|
||||||
FWNODE_ACPI,
|
FWNODE_ACPI,
|
||||||
FWNODE_PDATA,
|
FWNODE_PDATA,
|
||||||
|
FWNODE_IRQCHIP,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct fwnode_handle {
|
struct fwnode_handle {
|
||||||
|
|||||||
@@ -188,6 +188,8 @@ static inline struct device_node *irq_domain_get_of_node(struct irq_domain *d)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_IRQ_DOMAIN
|
#ifdef CONFIG_IRQ_DOMAIN
|
||||||
|
struct fwnode_handle *irq_domain_alloc_fwnode(void *data);
|
||||||
|
void irq_domain_free_fwnode(struct fwnode_handle *fwnode);
|
||||||
struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, int size,
|
struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, int size,
|
||||||
irq_hw_number_t hwirq_max, int direct_max,
|
irq_hw_number_t hwirq_max, int direct_max,
|
||||||
const struct irq_domain_ops *ops,
|
const struct irq_domain_ops *ops,
|
||||||
|
|||||||
@@ -27,6 +27,57 @@ static int irq_domain_alloc_descs(int virq, unsigned int nr_irqs,
|
|||||||
irq_hw_number_t hwirq, int node);
|
irq_hw_number_t hwirq, int node);
|
||||||
static void irq_domain_check_hierarchy(struct irq_domain *domain);
|
static void irq_domain_check_hierarchy(struct irq_domain *domain);
|
||||||
|
|
||||||
|
struct irqchip_fwid {
|
||||||
|
struct fwnode_handle fwnode;
|
||||||
|
char *name;
|
||||||
|
void *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* irq_domain_alloc_fwnode - Allocate a fwnode_handle suitable for
|
||||||
|
* identifying an irq domain
|
||||||
|
* @data: optional user-provided data
|
||||||
|
*
|
||||||
|
* Allocate a struct device_node, and return a poiner to the embedded
|
||||||
|
* fwnode_handle (or NULL on failure).
|
||||||
|
*/
|
||||||
|
struct fwnode_handle *irq_domain_alloc_fwnode(void *data)
|
||||||
|
{
|
||||||
|
struct irqchip_fwid *fwid;
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
fwid = kzalloc(sizeof(*fwid), GFP_KERNEL);
|
||||||
|
name = kasprintf(GFP_KERNEL, "irqchip@%p", data);
|
||||||
|
|
||||||
|
if (!fwid || !name) {
|
||||||
|
kfree(fwid);
|
||||||
|
kfree(name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fwid->name = name;
|
||||||
|
fwid->data = data;
|
||||||
|
fwid->fwnode.type = FWNODE_IRQCHIP;
|
||||||
|
return &fwid->fwnode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* irq_domain_free_fwnode - Free a non-OF-backed fwnode_handle
|
||||||
|
*
|
||||||
|
* Free a fwnode_handle allocated with irq_domain_alloc_fwnode.
|
||||||
|
*/
|
||||||
|
void irq_domain_free_fwnode(struct fwnode_handle *fwnode)
|
||||||
|
{
|
||||||
|
struct irqchip_fwid *fwid;
|
||||||
|
|
||||||
|
if (WARN_ON(fwnode->type != FWNODE_IRQCHIP))
|
||||||
|
return;
|
||||||
|
|
||||||
|
fwid = container_of(fwnode, struct irqchip_fwid, fwnode);
|
||||||
|
kfree(fwid->name);
|
||||||
|
kfree(fwid);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __irq_domain_add() - Allocate a new irq_domain data structure
|
* __irq_domain_add() - Allocate a new irq_domain data structure
|
||||||
* @of_node: optional device-tree node of the interrupt controller
|
* @of_node: optional device-tree node of the interrupt controller
|
||||||
|
|||||||
Reference in New Issue
Block a user