Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC] drivers: intc: plic: multi-instance support - approach 2 #62481

Closed
wants to merge 2 commits into from

Conversation

ycsin
Copy link
Member

@ycsin ycsin commented Sep 11, 2023

This PR add multi-instance support to the intc_plic driver. As all the IRQs are sharing the same ISR table, 2nd levels and onwards IRQs in one instance of a controller can collide with another in the ISR table.

To avoid this, the ISR should have an offset as large as the sum of the number of IRQs in the previous instances in the devicetree, so they dont get installed to the same index.

The RISCV's arch_irq_connect_dynamic then get this offset from the controller to install the ISR accordingly.

This PR aims to get a look and feel of the approach.


  1. Why dont we just let interrupt controller to install the ISR? practiced in this PR, for RISCV intc_plic only

@ycsin
Copy link
Member Author

ycsin commented Sep 11, 2023

cc @carlocaione

@ycsin ycsin force-pushed the pr/plic_multi_instance_0 branch from eb87551 to 1044109 Compare September 12, 2023 05:30
@ycsin ycsin changed the title drivers: intc: plic: initial refactor for multi-instance support drivers: intc: plic: multi-instance support Sep 12, 2023
@ycsin ycsin changed the title drivers: intc: plic: multi-instance support drivers: intc: plic: multi-instance support - approach 2 Sep 12, 2023
@ycsin ycsin force-pushed the pr/plic_multi_instance_0 branch from 1044109 to a5f21f9 Compare September 12, 2023 13:59
@ycsin ycsin marked this pull request as ready for review September 12, 2023 13:59
@zephyrbot zephyrbot added area: Interrupt Controller area: GPIO area: Architectures area: RISCV RISCV Architecture (32-bit & 64-bit) area: Devicetree Binding PR modifies or adds a Device Tree binding labels Sep 12, 2023
@ycsin ycsin force-pushed the pr/plic_multi_instance_0 branch 3 times, most recently from 7b438a1 to bac14c6 Compare September 15, 2023 12:59
@@ -5,6 +5,15 @@

menu "Interrupt controller drivers"

config MULTI_INSTANCE_INTC
Copy link
Member

@cfriedt cfriedt Sep 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shouldn't require a Kconfig - devicetree to describe hw, kconfig to describe sw

config MULTI_INSTANCE_INTC
bool

config HAS_MUTLI_INSTANCE_INTC
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this shouldn't require a kconfig

/**
* @brief Enable interrupt
*
* @param irq interrupt ID
*/
void riscv_plic_irq_enable(uint32_t irq);
void riscv_plic_irq_enable(uint32_t irq, const struct device *dev);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The signature for this should probably not be changed.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this approach, the IRQN doesn't carry information about the plic instance, so the dev is required


/**
* @brief Disable interrupt
*
* @param irq interrupt ID
*/
void riscv_plic_irq_disable(uint32_t irq);
void riscv_plic_irq_disable(uint32_t irq, const struct device *dev);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the signature for this should probably not be changed.


/**
* @brief Check if an interrupt is enabled
*
* @param irq interrupt ID
* @return Returns true if interrupt is enabled, false otherwise
*/
int riscv_plic_irq_is_enabled(uint32_t irq);
int riscv_plic_irq_is_enabled(uint32_t irq, const struct device *dev);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the signature for this should probably not be changed.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as the irq doesnt carry the interrupt controller info, an additional dev arg is required in a multi-instance configuration

*
* @return Returns the device struct of the interrupt controller
*/
const struct device *riscv_plic_get_dev(void);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There can be multiple active interrupts on separate cores - is that taken into consideration here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SMP is not considered in this PR

@@ -48,6 +48,20 @@ extern "C" {
#define IRQ_CONNECT(irq_p, priority_p, isr_p, isr_param_p, flags_p) \
ARCH_IRQ_CONNECT(irq_p, priority_p, isr_p, isr_param_p, flags_p)

#ifdef CONFIG_MULTI_INSTANCE_INTC
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No Kconfig is necessary

@@ -1237,7 +1240,8 @@ static const struct uart_driver_api uart_ns16550_driver_api = {
static void irq_config_func##n(const struct device *dev) \
{ \
ARG_UNUSED(dev); \
IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), \
NS16550_IRQ_CONNECT(DT_INST_INTC_PARENT(n), DT_INST_IRQN(n), \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this just be converted to use IRQ_INTC_CONNECT() directly? It also looks like the first parameter is supposed to be an instance number, but here it's a const struct device *.

Copy link
Member Author

@ycsin ycsin Sep 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this approach, the IRQN doesn't carry information about the plic instance, we will need to pass in the parent interrupt controller of the uart

@cfriedt
Copy link
Member

cfriedt commented Sep 15, 2023

This actually looks somewhat reasonable to me, except for all of the DT changes. We don't need to adjust vendor .dts or .dtsi to fix the driver. I would leave that stuff alone.

void z_riscv_plic_isr_install(unsigned int irq, unsigned int priority,
void (*routine)(const void *), const void *param)
{
z_riscv_plic_isr_intc_install(NULL, irq, priority, routine, param);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, we have the ability to get dev upfront, so might as well do that, and then it doesn't need to be done in z_riscv_plic_isr_intc_install()

@ycsin ycsin force-pushed the pr/plic_multi_instance_0 branch from bac14c6 to 70d98c7 Compare September 18, 2023 04:09
ARG_UNUSED(flags);

z_isr_install(irq, routine, parameter);

#if defined(CONFIG_RISCV_HAS_PLIC)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pardon my ignorance but won't this break the shared interrupt support on PLIC-based RISCV SoCs? z_riscv_plic_isr_intc_install() doesn't seem to be aware of the fact that the ISR may be set to z_shared_isr() and will overwrite it. Is this behavior desired?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I'm aware of this issue, the isr installer in the shared interrupt part has to be updated as well for this approach to work.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pardon my ignorance but won't this break the shared interrupt support on PLIC-based RISCV SoCs? z_riscv_plic_isr_intc_install() doesn't seem to be aware of the fact that the ISR may be set to z_shared_isr() and will overwrite it. Is this behavior desired?

@LaurentiuM1234 - IIRC you recently updated the shared interrupt code. Were multi-level interrupts taken into account in the shared interrupt design?

If so, what would be the best way to support them?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@LaurentiuM1234 - IIRC you recently updated the shared interrupt code. Were multi-level interrupts taken into account in the shared interrupt design?

Yes the shared interrupt code is aware of the multi-level organization of the interrupts via z_get_sw_isr_table_idx() (for dynamic interrupts)

If so, what would be the best way to support them?

Mm, not sure how helpful I can be here since I'm not familiar with RISCV and its quirks. If the multiple PLIC instances are basically aggregators for different interrupt lines I would suggest taking a look at #62776. The idea is that you register a dispatcher for each of these interrupt lines which will, in turn, call of the higher level reigstered ISRs. z_isr_install() is kept unchanged to keep the support for shared interrupts.

Use a config struct to store per-instance device config during
init and connect the IRQ based on the devicetree instead of
hardcoded value and instance.

The `get_plic_dev_from_irq` is still a placeholder for now and
always return the first instance.

Signed-off-by: Yong Cong Sin <ycsin@meta.com>
Extends the `riscv_plic` public header to provide an ISR
installer. The ISR installer implementation in the `intc_plic`
will install the ISR to the correct offset using infomation
from the devicetree properties.

The RISCV's `arch_irq_connect_dynamic` will use this ISR
installer when `CONFIG_RISCV_HAS_PLIC` is enabled.

Signed-off-by: Yong Cong Sin <ycsin@meta.com>
@ycsin ycsin force-pushed the pr/plic_multi_instance_0 branch from 70d98c7 to a1b9134 Compare September 19, 2023 03:53
@ycsin ycsin closed this Sep 25, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: Architectures area: Devicetree Binding PR modifies or adds a Device Tree binding area: GPIO area: Interrupt Controller area: RISCV RISCV Architecture (32-bit & 64-bit)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[RFC][RISCV] Support for multiple instances of multi-level interrupt controller
6 participants