Re: [RFC] powerpc/irq: Add generic API for setting up cascaded IRQs
I'm a reverse polish kind of guy. I preferring 'subject'_'action' over 'action'_'subject' just because it groups like subjects together. But it doesn't matter much, especially in this case where 'subject' is in a group of exactly 1. :-) I'll do whichever you prefer. I just caught myself calling something relocs_check instead of check_relocs so I suppose it's fair game :-) Whatever you want. Cheers, Ben. ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [RFC] powerpc/irq: Add generic API for setting up cascaded IRQs
On Tue, 2009-09-15 at 20:02 +1000, Benjamin Herrenschmidt wrote: I'm a reverse polish kind of guy. I preferring 'subject'_'action' over 'action'_'subject' just because it groups like subjects together. But it doesn't matter much, especially in this case where 'subject' is in a group of exactly 1. :-) I'll do whichever you prefer. I just caught myself calling something relocs_check instead of check_relocs so I suppose it's fair game :-) Yeah but that sounds stupid :) Whatever you want. I want a pony. And setup_cascade() is definitely better IMHO. cheers signature.asc Description: This is a digitally signed message part ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [RFC] powerpc/irq: Add generic API for setting up cascaded IRQs
On Fri, 2009-09-11 at 23:46 -0600, Grant Likely wrote: From: Grant Likely grant.lik...@secretlab.ca prototype implementation. This probably doesn't work at all right now. Ben, I'm posting this now to get your thoughts before I go too far down this path. Looks ok. I was initially thinking about putting get_irq() in irq_host, but as we discussed on IRC, a host is not necessarily a PIC, and it's nice for the parent to have a way to setup/init the cascade in case it needs to do some HW tweaking there as well. However, why cascade_setup() and not setup_cascade() which sounds somewhat more natural ? :-) Cheers, Ben. Cheers, g. --- arch/powerpc/include/asm/irq.h|3 ++ arch/powerpc/kernel/irq.c | 20 +++ arch/powerpc/platforms/52xx/mpc52xx_pic.c | 39 + 3 files changed, 62 insertions(+), 0 deletions(-) diff --git a/arch/powerpc/include/asm/irq.h b/arch/powerpc/include/asm/irq.h index 0a51376..014e1e8 100644 --- a/arch/powerpc/include/asm/irq.h +++ b/arch/powerpc/include/asm/irq.h @@ -90,6 +90,9 @@ struct irq_host_ops { /* Update of such a mapping */ void (*remap)(struct irq_host *h, unsigned int virq, irq_hw_number_t hw); + /* Setup hook for cascade irqs */ + int (*cascade_setup)(int virq, int (*get_irq)(void *data), void *data); + /* Translate device-tree interrupt specifier from raw format coming * from the firmware to a irq_hw_number_t (interrupt line number) and * type (sense) that can be passed to set_irq_type(). In the absence diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index f7f376e..5a9cb46 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -750,6 +750,26 @@ unsigned int irq_of_parse_and_map(struct device_node *dev, int index) } EXPORT_SYMBOL_GPL(irq_of_parse_and_map); +unsigned int irq_of_cascade_setup(int virq, int (*get_irq)(void *data), + void *data) +{ + struct irq_host *host = irq_map[virq].host; + + if (!host) { + pr_err(error: no irq host found virq %i !\n, virq); + return -ENODEV; + } + + /* If host has no cascade setup function, then this method for + * setting up a cascade is not available */ + if (!host-ops-cascade_setup) { + pr_err(error: no cascade_setup support on virq %i\n, virq); + return -EINVAL; + } + + return host-ops-cascade_setup(virq, get_irq, data); +} + void irq_dispose_mapping(unsigned int virq) { struct irq_host *host; diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pic.c b/arch/powerpc/platforms/52xx/mpc52xx_pic.c index 480f806..a91c69b 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_pic.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_pic.c @@ -437,9 +437,48 @@ static int mpc52xx_irqhost_map(struct irq_host *h, unsigned int virq, return 0; } +struct mpc52xx_cascade_data { + int (*get_irq)(void *data); + void *data; +}; + +void mpc52xx_handle_level_cascade(unsigned int irq, struct irq_desc *desc) +{ + struct mpc52xx_cascade_data *cascade_data = get_irq_desc_data(desc); + int cascade_virq; + + cascade_virq = cascade_data-get_irq(cascade_data-data); + if (cascade_virq) + generic_handle_irq(cascade_virq); +} + +void mpc52xx_handle_edge_cascade(unsigned int virq, struct irq_desc *desc) +{ + mpc52xx_handle_level_cascade(virq, desc); + /** TODO: clear edge IRQ here **/ +} + +int mpc52xx_cascade_setup(int virq, int (*get_irq)(void *data), void *data) +{ + struct mpc52xx_cascade_data *cascade_data; + + cascade_data = kzalloc(sizeof(struct mpc52xx_cascade_data), GFP_KERNEL); + if (!cascade_data) + return -ENOMEM; + + /* TODO: make this handle edge cascades too */ + cascade_data-get_irq = get_irq; + cascade_data-data = data; + set_irq_data(virq, cascade_data); + set_irq_chained_handler(virq, mpc52xx_handle_level_cascade); + + return 0; +} + static struct irq_host_ops mpc52xx_irqhost_ops = { .xlate = mpc52xx_irqhost_xlate, .map = mpc52xx_irqhost_map, + .cascade_setup = mpc52xx_cascade_setup, }; /** ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [RFC] powerpc/irq: Add generic API for setting up cascaded IRQs
On Sat, Sep 12, 2009 at 12:28 AM, Benjamin Herrenschmidt b...@kernel.crashing.org wrote: On Fri, 2009-09-11 at 23:46 -0600, Grant Likely wrote: From: Grant Likely grant.lik...@secretlab.ca prototype implementation. This probably doesn't work at all right now. Ben, I'm posting this now to get your thoughts before I go too far down this path. Looks ok. I was initially thinking about putting get_irq() in irq_host, but as we discussed on IRC, a host is not necessarily a PIC, and it's nice for the parent to have a way to setup/init the cascade in case it needs to do some HW tweaking there as well. Cool. Thanks for the review. I'll continue on with this approach and hopefully get something working this weekend. However, why cascade_setup() and not setup_cascade() which sounds somewhat more natural ? :-) I'm a reverse polish kind of guy. I preferring 'subject'_'action' over 'action'_'subject' just because it groups like subjects together. But it doesn't matter much, especially in this case where 'subject' is in a group of exactly 1. :-) I'll do whichever you prefer. g. -- Grant Likely, B.Sc., P.Eng. Secret Lab Technologies Ltd. ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[RFC] powerpc/irq: Add generic API for setting up cascaded IRQs
From: Grant Likely grant.lik...@secretlab.ca prototype implementation. This probably doesn't work at all right now. Ben, I'm posting this now to get your thoughts before I go too far down this path. Cheers, g. --- arch/powerpc/include/asm/irq.h|3 ++ arch/powerpc/kernel/irq.c | 20 +++ arch/powerpc/platforms/52xx/mpc52xx_pic.c | 39 + 3 files changed, 62 insertions(+), 0 deletions(-) diff --git a/arch/powerpc/include/asm/irq.h b/arch/powerpc/include/asm/irq.h index 0a51376..014e1e8 100644 --- a/arch/powerpc/include/asm/irq.h +++ b/arch/powerpc/include/asm/irq.h @@ -90,6 +90,9 @@ struct irq_host_ops { /* Update of such a mapping */ void (*remap)(struct irq_host *h, unsigned int virq, irq_hw_number_t hw); + /* Setup hook for cascade irqs */ + int (*cascade_setup)(int virq, int (*get_irq)(void *data), void *data); + /* Translate device-tree interrupt specifier from raw format coming * from the firmware to a irq_hw_number_t (interrupt line number) and * type (sense) that can be passed to set_irq_type(). In the absence diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index f7f376e..5a9cb46 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -750,6 +750,26 @@ unsigned int irq_of_parse_and_map(struct device_node *dev, int index) } EXPORT_SYMBOL_GPL(irq_of_parse_and_map); +unsigned int irq_of_cascade_setup(int virq, int (*get_irq)(void *data), + void *data) +{ + struct irq_host *host = irq_map[virq].host; + + if (!host) { + pr_err(error: no irq host found virq %i !\n, virq); + return -ENODEV; + } + + /* If host has no cascade setup function, then this method for +* setting up a cascade is not available */ + if (!host-ops-cascade_setup) { + pr_err(error: no cascade_setup support on virq %i\n, virq); + return -EINVAL; + } + + return host-ops-cascade_setup(virq, get_irq, data); +} + void irq_dispose_mapping(unsigned int virq) { struct irq_host *host; diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pic.c b/arch/powerpc/platforms/52xx/mpc52xx_pic.c index 480f806..a91c69b 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_pic.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_pic.c @@ -437,9 +437,48 @@ static int mpc52xx_irqhost_map(struct irq_host *h, unsigned int virq, return 0; } +struct mpc52xx_cascade_data { + int (*get_irq)(void *data); + void *data; +}; + +void mpc52xx_handle_level_cascade(unsigned int irq, struct irq_desc *desc) +{ + struct mpc52xx_cascade_data *cascade_data = get_irq_desc_data(desc); + int cascade_virq; + + cascade_virq = cascade_data-get_irq(cascade_data-data); + if (cascade_virq) + generic_handle_irq(cascade_virq); +} + +void mpc52xx_handle_edge_cascade(unsigned int virq, struct irq_desc *desc) +{ + mpc52xx_handle_level_cascade(virq, desc); + /** TODO: clear edge IRQ here **/ +} + +int mpc52xx_cascade_setup(int virq, int (*get_irq)(void *data), void *data) +{ + struct mpc52xx_cascade_data *cascade_data; + + cascade_data = kzalloc(sizeof(struct mpc52xx_cascade_data), GFP_KERNEL); + if (!cascade_data) + return -ENOMEM; + + /* TODO: make this handle edge cascades too */ + cascade_data-get_irq = get_irq; + cascade_data-data = data; + set_irq_data(virq, cascade_data); + set_irq_chained_handler(virq, mpc52xx_handle_level_cascade); + + return 0; +} + static struct irq_host_ops mpc52xx_irqhost_ops = { .xlate = mpc52xx_irqhost_xlate, .map = mpc52xx_irqhost_map, + .cascade_setup = mpc52xx_cascade_setup, }; /** ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev