From: miquel.raynal@bootlin.com (Miquel Raynal)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v2 09/16] irqchip/irq-mvebu-sei: add new driver for Marvell SEI
Date: Fri, 8 Jun 2018 12:26:09 +0200 [thread overview]
Message-ID: <20180608122609.0bb051f6@xps13> (raw)
In-Reply-To: <b11849f0-3593-51e1-8d4f-b05bfe6412a1@arm.com>
Hi Marc,
> > +static struct irq_chip mvebu_sei_ap_wired_irq_chip = {
> > + .name = "AP wired SEI",
> > + .irq_mask = mvebu_sei_mask_irq,
> > + .irq_unmask = mvebu_sei_unmask_irq,
> > + .irq_eoi = irq_chip_eoi_parent,
> > + .irq_set_affinity = irq_chip_set_affinity_parent,
> > + .irq_set_type = irq_chip_set_type_parent,
>
> You seem to assume that this driver is purely dealing with edge
> interrupts. And yet you pass the request directly to the parrent. What
> does it mean? Shouldn't you at least check that this is an edge request
> and fail otherwise?
MSI are rising-edge interrupts while wired ones are level (high)
interrupts. I will correct this.
> > + irq_chip = &mvebu_sei_ap_wired_irq_chip;
> > + hwirq = fwspec->param[0];
> > + } else {
> > + irq_chip = &mvebu_sei_cp_msi_irq_chip;
> > + spin_lock(&sei->cp_msi_lock);
>
> This could as well be a mutex.
Ok.
>
> > + hwirq = bitmap_find_free_region(sei->cp_msi_bitmap,
> > + SEI_IRQ_COUNT, 0);
>
> It is a bit weird that you're allocating from a 64bit bitmap while you
> only have 43 interrupts available... At the 44th interrupt, something
> bad is going to happen.
Absolutely, to solve this issue, I just had to:
s/SEI_IRQ_COUNT/sei->cp_interrupts.number/
>
> > + spin_unlock(&sei->cp_msi_lock);
> > + if (hwirq < 0)
> > + return -ENOSPC;
> > + }
> > +
[...]
> > +static void mvebu_sei_handle_cascade_irq(struct irq_desc *desc)
> > +{
> > + struct mvebu_sei *sei = irq_desc_get_handler_data(desc);
> > + struct irq_chip *chip = irq_desc_get_chip(desc);
> > + unsigned long irqmap, irq_bit;
> > + u32 reg_idx, virq, irqn;
> > +
> > + chained_irq_enter(chip, desc);
> > +
> > + /* Read both SEI cause registers (64 bits) */
> > + for (reg_idx = 0; reg_idx < SEI_IRQ_REG_COUNT; reg_idx++) {
> > + irqmap = readl_relaxed(sei->base + GICP_SECR(reg_idx));
> > +
> > + /* Call handler for each set bit */
> > + for_each_set_bit(irq_bit, &irqmap, SEI_IRQ_COUNT_PER_REG) {
> > + /* Cause Register gives the SEI number */
> > + irqn = irq_bit + reg_idx * SEI_IRQ_COUNT_PER_REG;
> > + /*
> > + * Finding Linux mapping (virq) needs the right domain
> > + * and the relative hwirq (which start at 0 in both
> > + * cases, while irqn is relative to all SEI interrupts).
> > + */
>
> It is a bit odd that you're virtualizing the hwirq number. The whole
> point of splitting hwirq from virq is that you don't have to do that and
> can use the the raw HW number. You're saving a tiny bit of memory in the
> irq_domain, at the expense of more complexity. I don't know if that's
> worth it...
>
> > + if (irqn < sei->ap_interrupts.number) {
> > + virq = irq_find_mapping(sei->ap_domain, irqn);
> > + } else {
> > + irqn -= sei->ap_interrupts.number;
> > + virq = irq_find_mapping(sei->cp_domain, irqn);
> > + }
> > +
> > + /* Call IRQ handler */
> > + generic_handle_irq(virq);
> > + }
> > +
> > + /* Clear interrupt indication by writing 1 to it */
> > + writel(irqmap, sei->base + GICP_SECR(reg_idx));
> > + }
> > +
> > + chained_irq_exit(chip, desc);
> > +}
[...]
> It feels like this patch could do with a total split:
>
> - Introduce the wired side of the driver
> - then the MSI part
>
> Drop the common domain callbacks, and treat the two domains separately.
> I seriously doubt there will be much of an overlap anyway.
Maybe I don't get what "saving a tiny bit of memory" really means in
this situation. What I am doing right now is duplicating hundreds of
lines and changing things like:
sei_hwirq = mvebu_sei_domain_to_sei_irq(..., hwirq)
into
sei_hwirq = sei->ap_interrupts.first + d->hwirq;
and
sei_hwirq = sei->cp_interrupts.first + d->hwirq;
because I still need to translate this hwirq number into an offset
within 64 bits. In fact, for each configuration/management operation
like clearing, checking or masking an interrupt, a bit must be twisted
within a pair of registers. This offset cannot be just the hwirq
number, it must be shifted depending on the IRQ domain/type of
interrupt.
I'm sorry but I will need more guidance on this because I don't see the
point in duplicating so much code that was factorized.
Thanks,
Miqu?l
WARNING: multiple messages have this Message-ID (diff)
From: Miquel Raynal <miquel.raynal@bootlin.com>
To: Marc Zyngier <marc.zyngier@arm.com>
Cc: Thomas Gleixner <tglx@linutronix.de>,
Jason Cooper <jason@lakedaemon.net>,
Catalin Marinas <catalin.marinas@arm.com>,
Will Deacon <will.deacon@arm.com>, Andrew Lunn <andrew@lunn.ch>,
Gregory Clement <gregory.clement@bootlin.com>,
Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>,
Rob Herring <robh+dt@kernel.org>,
Mark Rutland <mark.rutland@arm.com>,
devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
Thomas Petazzoni <thomas.petazzoni@bootlin.com>,
Antoine Tenart <antoine.tenart@bootlin.com>,
Maxime Chevallier <maxime.chevallier@bootlin.com>,
Nadav Haklai <nadavh@marvell.com>, Haim Boot <hayim@marvell.com>,
Hanna Hawa <hannah@marvell.com>,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH v2 09/16] irqchip/irq-mvebu-sei: add new driver for Marvell SEI
Date: Fri, 8 Jun 2018 12:26:09 +0200 [thread overview]
Message-ID: <20180608122609.0bb051f6@xps13> (raw)
In-Reply-To: <b11849f0-3593-51e1-8d4f-b05bfe6412a1@arm.com>
Hi Marc,
> > +static struct irq_chip mvebu_sei_ap_wired_irq_chip = {
> > + .name = "AP wired SEI",
> > + .irq_mask = mvebu_sei_mask_irq,
> > + .irq_unmask = mvebu_sei_unmask_irq,
> > + .irq_eoi = irq_chip_eoi_parent,
> > + .irq_set_affinity = irq_chip_set_affinity_parent,
> > + .irq_set_type = irq_chip_set_type_parent,
>
> You seem to assume that this driver is purely dealing with edge
> interrupts. And yet you pass the request directly to the parrent. What
> does it mean? Shouldn't you at least check that this is an edge request
> and fail otherwise?
MSI are rising-edge interrupts while wired ones are level (high)
interrupts. I will correct this.
> > + irq_chip = &mvebu_sei_ap_wired_irq_chip;
> > + hwirq = fwspec->param[0];
> > + } else {
> > + irq_chip = &mvebu_sei_cp_msi_irq_chip;
> > + spin_lock(&sei->cp_msi_lock);
>
> This could as well be a mutex.
Ok.
>
> > + hwirq = bitmap_find_free_region(sei->cp_msi_bitmap,
> > + SEI_IRQ_COUNT, 0);
>
> It is a bit weird that you're allocating from a 64bit bitmap while you
> only have 43 interrupts available... At the 44th interrupt, something
> bad is going to happen.
Absolutely, to solve this issue, I just had to:
s/SEI_IRQ_COUNT/sei->cp_interrupts.number/
>
> > + spin_unlock(&sei->cp_msi_lock);
> > + if (hwirq < 0)
> > + return -ENOSPC;
> > + }
> > +
[...]
> > +static void mvebu_sei_handle_cascade_irq(struct irq_desc *desc)
> > +{
> > + struct mvebu_sei *sei = irq_desc_get_handler_data(desc);
> > + struct irq_chip *chip = irq_desc_get_chip(desc);
> > + unsigned long irqmap, irq_bit;
> > + u32 reg_idx, virq, irqn;
> > +
> > + chained_irq_enter(chip, desc);
> > +
> > + /* Read both SEI cause registers (64 bits) */
> > + for (reg_idx = 0; reg_idx < SEI_IRQ_REG_COUNT; reg_idx++) {
> > + irqmap = readl_relaxed(sei->base + GICP_SECR(reg_idx));
> > +
> > + /* Call handler for each set bit */
> > + for_each_set_bit(irq_bit, &irqmap, SEI_IRQ_COUNT_PER_REG) {
> > + /* Cause Register gives the SEI number */
> > + irqn = irq_bit + reg_idx * SEI_IRQ_COUNT_PER_REG;
> > + /*
> > + * Finding Linux mapping (virq) needs the right domain
> > + * and the relative hwirq (which start at 0 in both
> > + * cases, while irqn is relative to all SEI interrupts).
> > + */
>
> It is a bit odd that you're virtualizing the hwirq number. The whole
> point of splitting hwirq from virq is that you don't have to do that and
> can use the the raw HW number. You're saving a tiny bit of memory in the
> irq_domain, at the expense of more complexity. I don't know if that's
> worth it...
>
> > + if (irqn < sei->ap_interrupts.number) {
> > + virq = irq_find_mapping(sei->ap_domain, irqn);
> > + } else {
> > + irqn -= sei->ap_interrupts.number;
> > + virq = irq_find_mapping(sei->cp_domain, irqn);
> > + }
> > +
> > + /* Call IRQ handler */
> > + generic_handle_irq(virq);
> > + }
> > +
> > + /* Clear interrupt indication by writing 1 to it */
> > + writel(irqmap, sei->base + GICP_SECR(reg_idx));
> > + }
> > +
> > + chained_irq_exit(chip, desc);
> > +}
[...]
> It feels like this patch could do with a total split:
>
> - Introduce the wired side of the driver
> - then the MSI part
>
> Drop the common domain callbacks, and treat the two domains separately.
> I seriously doubt there will be much of an overlap anyway.
Maybe I don't get what "saving a tiny bit of memory" really means in
this situation. What I am doing right now is duplicating hundreds of
lines and changing things like:
sei_hwirq = mvebu_sei_domain_to_sei_irq(..., hwirq)
into
sei_hwirq = sei->ap_interrupts.first + d->hwirq;
and
sei_hwirq = sei->cp_interrupts.first + d->hwirq;
because I still need to translate this hwirq number into an offset
within 64 bits. In fact, for each configuration/management operation
like clearing, checking or masking an interrupt, a bit must be twisted
within a pair of registers. This offset cannot be just the hwirq
number, it must be shifted depending on the IRQ domain/type of
interrupt.
I'm sorry but I will need more guidance on this because I don't see the
point in duplicating so much code that was factorized.
Thanks,
Miquèl
next prev parent reply other threads:[~2018-06-08 10:26 UTC|newest]
Thread overview: 58+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-05-22 9:40 [PATCH v2 00/16] Add System Error Interrupt support to Armada SoCs Miquel Raynal
2018-05-22 9:40 ` Miquel Raynal
2018-05-22 9:40 ` [PATCH v2 01/16] dt-bindings/interrupt-controller: fix Marvell ICU length in the example Miquel Raynal
2018-05-22 9:40 ` Miquel Raynal
2018-05-22 9:40 ` [PATCH v2 02/16] arm64: dts: marvell: fix CP110 ICU node size Miquel Raynal
2018-05-22 9:40 ` Miquel Raynal
2018-05-23 7:36 ` Gregory CLEMENT
2018-05-23 7:36 ` Gregory CLEMENT
2018-05-22 9:40 ` [PATCH v2 03/16] irqchip/irq-mvebu-icu: fix wrong private data retrieval Miquel Raynal
2018-05-22 9:40 ` Miquel Raynal
2018-05-22 9:40 ` [PATCH v2 04/16] irqchip/irq-mvebu-icu: clarify the reset operation of configured interrupts Miquel Raynal
2018-05-22 9:40 ` Miquel Raynal
2018-05-22 9:40 ` [PATCH v2 05/16] irqchip/irq-mvebu-icu: switch to regmap Miquel Raynal
2018-05-22 9:40 ` Miquel Raynal
2018-05-22 9:40 ` [PATCH v2 06/16] irqchip/irq-mvebu-icu: make irq_domain local Miquel Raynal
2018-05-22 9:40 ` Miquel Raynal
2018-05-22 9:40 ` Miquel Raynal
2018-05-22 9:40 ` [PATCH v2 07/16] irqchip/irq-mvebu-icu: disociate ICU and NSR Miquel Raynal
2018-05-22 9:40 ` Miquel Raynal
2018-05-22 9:40 ` [PATCH v2 08/16] irqchip/irq-mvebu-icu: support ICU subnodes Miquel Raynal
2018-05-22 9:40 ` Miquel Raynal
2018-05-22 9:40 ` [PATCH v2 09/16] irqchip/irq-mvebu-sei: add new driver for Marvell SEI Miquel Raynal
2018-05-22 9:40 ` Miquel Raynal
2018-05-23 14:05 ` Marc Zyngier
2018-05-23 14:05 ` Marc Zyngier
2018-06-08 10:26 ` Miquel Raynal [this message]
2018-06-08 10:26 ` Miquel Raynal
2018-05-22 9:40 ` [PATCH v2 10/16] arm64: marvell: enable SEI driver Miquel Raynal
2018-05-22 9:40 ` Miquel Raynal
2018-05-22 9:40 ` [PATCH v2 11/16] irqchip/irq-mvebu-icu: add support for System Error Interrupts (SEI) Miquel Raynal
2018-05-22 9:40 ` Miquel Raynal
2018-05-23 14:23 ` Marc Zyngier
2018-05-23 14:23 ` Marc Zyngier
2018-06-08 13:08 ` Miquel Raynal
2018-06-08 13:08 ` Miquel Raynal
2018-05-22 9:40 ` [PATCH v2 12/16] dt-bindings/interrupt-controller: update Marvell ICU bindings Miquel Raynal
2018-05-22 9:40 ` Miquel Raynal
2018-06-05 20:29 ` Rob Herring
2018-06-05 20:29 ` Rob Herring
2018-06-05 20:35 ` Thomas Petazzoni
2018-06-05 20:35 ` Thomas Petazzoni
2018-06-08 14:00 ` Miquel Raynal
2018-06-08 14:00 ` Miquel Raynal
2018-06-08 21:34 ` Rob Herring
2018-05-22 9:40 ` [PATCH v2 13/16] dt-bindings/interrupt-controller: add documentation for Marvell SEI controller Miquel Raynal
2018-05-22 9:40 ` Miquel Raynal
2018-06-05 20:51 ` Rob Herring
2018-06-05 20:51 ` Rob Herring
2018-06-08 14:46 ` Miquel Raynal
2018-06-08 14:46 ` Miquel Raynal
2018-06-22 14:57 ` Miquel Raynal
2018-06-22 14:57 ` Miquel Raynal
2018-05-22 9:40 ` [PATCH v2 14/16] arm64: dts: marvell: add AP806 SEI subnode Miquel Raynal
2018-05-22 9:40 ` Miquel Raynal
2018-05-22 9:40 ` [PATCH v2 15/16] arm64: dts: marvell: use new bindings for CP110 interrupts Miquel Raynal
2018-05-22 9:40 ` Miquel Raynal
2018-05-22 9:40 ` [PATCH v2 16/16] arm64: dts: marvell: add CP110 ICU SEI subnode Miquel Raynal
2018-05-22 9:40 ` Miquel Raynal
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180608122609.0bb051f6@xps13 \
--to=miquel.raynal@bootlin.com \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.