lkml.org 
[lkml]   [2022]   [Jun]   [1]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
SubjectRe: [PATCH RFC V2 02/10] irqchip: Add LoongArch CPU interrupt controller support
From
Date
>>>> +
>>>> +int acpi_gsi_to_irq(u32 gsi, unsigned int *irqp)
>>>> +{
>>>> + if (irqp != NULL)
>>>> + *irqp = acpi_register_gsi(NULL, gsi, -1, -1);
>>>> + return (*irqp >= 0) ? 0 : -EINVAL;
>>>> +}
>>>> +EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);
>>>> +
>>>> +int acpi_isa_irq_to_gsi(unsigned int isa_irq, u32 *gsi)
>>>> +{
>>>> + if (gsi)
>>>> + *gsi = isa_irq;
>>>> + return 0;
>>>> +}
>>>> +
>>>> +/*
>>>> + * success: return IRQ number (>=0)
>>>> + * failure: return < 0
>>>> + */
>>>> +int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
>>>> +{
>>>> + int id;
>>>> + struct irq_fwspec fwspec;
>>>> +
>>>> + switch (gsi) {
>>>> + case GSI_MIN_CPU_IRQ ... GSI_MAX_CPU_IRQ:
>>>> + fwspec.fwnode = liointc_domain->fwnode;
>>>> + fwspec.param[0] = gsi - GSI_MIN_CPU_IRQ;
>>>> + fwspec.param_count = 1;
>>>> +
>>>> + return irq_create_fwspec_mapping(&fwspec);
>>>> +
>>>> + case GSI_MIN_LPC_IRQ ... GSI_MAX_LPC_IRQ:
>>>> + if (!pch_lpc_domain)
>>>> + return -EINVAL;
>>>> +
>>>> + fwspec.fwnode = pch_lpc_domain->fwnode;
>>>> + fwspec.param[0] = gsi - GSI_MIN_LPC_IRQ;
>>>> + fwspec.param[1] = acpi_dev_get_irq_type(trigger, polarity);
>>>> + fwspec.param_count = 2;
>>>> +
>>>> + return irq_create_fwspec_mapping(&fwspec);
>>>> +
>>>> + case GSI_MIN_PCH_IRQ ... GSI_MAX_PCH_IRQ:
>>>> + id = find_pch_pic(gsi);
>>>> + if (id < 0)
>>>> + return -EINVAL;
>>>> +
>>>> + fwspec.fwnode = pch_pic_domain[id]->fwnode;
>>>> + fwspec.param[0] = gsi - acpi_pchpic[id]->gsi_base;
>>>> + fwspec.param[1] = IRQ_TYPE_LEVEL_HIGH;
>>>> + fwspec.param_count = 2;
>>>> +
>>>> + return irq_create_fwspec_mapping(&fwspec);
>>>> + }
>>> So all the complexity here seems to stem from the fact that you deal
>>> with three ranges of interrupts, managed by three different pieces of
>>> code?
>>>
>> Yes.
>>
>>> Other architectures have similar requirements, and don't require to
>>> re-implement a private version of the ACPI API. Instead, they expose a
>>> single irqdomain, and deal with the various ranges internally.
>>>
>>> Clearly, not being able to reuse drivers/acpi/irq.c *is* an issue.
>>>
>> Thanks, I agree, that sounds a good and reasonable suggestion, and
>> I'll reserach it further and reuse code from drivers/acpi/irq.c as
>> can as possible.
>>
Hi, Marc, according to your suggestion, I carefully looked into gic
driver of ARM, and I found one possible gsi mapping path as following:

acpi_register_gsi /* whatever the gsi is, gic domain for ARM is only
single domain to use.*/
 ->irq_create_fwspec_mapping
   ->irq_find_mapping /* return irq in the mapping of irqdomain with
fwnode_handle of acpi_gsi_domain_id if configured. */
   ->irq_domain_alloc_irqs /* if not configured and hierarchy domain */
     ->irq_domain_alloc_irqs_hierarchy
       ->domain->ops->alloc /* call gic_irq_domain_alloc */
         ->gic_irq_domain_map /* handle different GSI range as
following code: */


        switch (__get_intid_range(hw)) {
        case SGI_RANGE:
        case PPI_RANGE:
        case EPPI_RANGE:
                irq_set_percpu_devid(irq);
                irq_domain_set_info(d, irq, hw, chip, d->host_data,
                                    handle_percpu_devid_irq, NULL, NULL);
                break;

        case SPI_RANGE:
        case ESPI_RANGE:
                irq_domain_set_info(d, irq, hw, chip, d->host_data,
                                    handle_fasteoi_irq, NULL, NULL);
                irq_set_probe(irq);
                irqd_set_single_target(irqd);
                break;

        case LPI_RANGE:
                if (!gic_dist_supports_lpis())
                        return -EPERM;
                irq_domain_set_info(d, irq, hw, chip, d->host_data,
                                    handle_fasteoi_irq, NULL, NULL);
                break;

Yes, it's well for ARM by this way, and I found that only one
domain(specified by acpi_gsi_domain_id)is used.

But for LoongArch, different GSI range have to be handled in different
domain(e.g. GSI for LIOINTC irqchip can be only mapped in LIOINTC
domain.). The hwirq->irq mapping of different GSI range is stored in
related separate domain. The reason leading to this is that an interrupt
source is hardcodingly to connected to an interrupt vector for these
irqchip(LIOINTC,LPC-PIC and PCH-PIC), and the interrupt source of them
need to be configured with GSI in DSDT or FADT(e.g. SCI).

If only exposing one domain for LoongArch, when calling irq_find_mapping
in acpi_register_gsi flow, the irq is returned only from the domain
specfied by acpi_gsi_domain_id, so I'm afraid it's unsuitable to expose
a single domain for acpi_register_gsi.

I'm so sorry, I really don't find a way to reuse driver/acpi/irq.c after
my humble work.

\
 
 \ /
  Last update: 2022-06-02 05:20    [W:0.416 / U:0.032 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site