Skip to content

Commit

Permalink
irqdomain: Add a fwnode_handle allocator
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Marc Zyngier authored and Thomas Gleixner committed Oct 13, 2015
1 parent 1bf4ddc commit b145dcc
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 0 deletions.
1 change: 1 addition & 0 deletions include/linux/fwnode.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ enum fwnode_type {
FWNODE_OF,
FWNODE_ACPI,
FWNODE_PDATA,
FWNODE_IRQCHIP,
};

struct fwnode_handle {
Expand Down
2 changes: 2 additions & 0 deletions include/linux/irqdomain.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,8 @@ static inline struct device_node *irq_domain_get_of_node(struct irq_domain *d)
}

#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,
irq_hw_number_t hwirq_max, int direct_max,
const struct irq_domain_ops *ops,
Expand Down
51 changes: 51 additions & 0 deletions kernel/irq/irqdomain.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,57 @@ static int irq_domain_alloc_descs(int virq, unsigned int nr_irqs,
irq_hw_number_t hwirq, int node);
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
* @of_node: optional device-tree node of the interrupt controller
Expand Down

0 comments on commit b145dcc

Please sign in to comment.