Subject: [RFT v2 01/24] irqdomain: Introduce new interfaces to support hierarchy irqdomains

From: [email-masked] (Jiang Liu)
Date: Tue, 07 Oct 2014 09:26:02 +0800

Hi Abel,
	Thanks for review. I was on Chinese National Holiday and
didn't have internet access in last a few days:)

On 2014/9/29 20:22, Abel wrote:
> Hi Jiang,
> Please see my comments and questions below.
> On 2014/9/26 22:02, Jiang Liu wrote:
> 
> [...]
>> diff --git a/kernel/irq/Kconfig b/kernel/irq/Kconfig
>> index d269cecdfbf0..dc1f3d08892e 100644
>> --- a/kernel/irq/Kconfig
>> +++ b/kernel/irq/Kconfig
>> @@ -55,6 +55,9 @@ config GENERIC_IRQ_CHIP
>>  config IRQ_DOMAIN
>>  	bool
>>  
>> +config IRQ_DOMAIN_HIERARCHY
>> +	bool
>> +
> 
> Depends on IRQ_DOMAIN?
True, will add the dependency.

> 
>>  config IRQ_DOMAIN_DEBUG
>>  	bool "Expose hardware/virtual IRQ mapping via debugfs"
>>  	depends on IRQ_DOMAIN && DEBUG_FS
> [...]
> 
>> +static void irq_domain_free_descs(unsigned int virq, unsigned int nr_irqs)
>> +{
>> +	unsigned int i;
>> +
>> +	for (i = 0; i < nr_irqs; i++)
>> +		irq_free_desc(virq + i);
>> +}
> 
> I am not sure why this function is needed, since it works in the exact same
> way as irq_free_descs(virq, nr_irqs).
Good suggestion, will kill the redundant irq_domain_free_descs().

> 
>> +
> [...]
>> +/**
>> + * __irq_domain_alloc_irqs - Allocate IRQs from domain
>> + * @domain: domain to allocate from
>> + * @irq_base: allocate specified IRQ nubmer if irq_base >= 0
>> + * @nr_irqs: number of IRQs to allocate
>> + * @node: NUMA node id for memory allocation
>> + * @arg: domain specific argument
>> + * @realloc: IRQ descriptors have already been allocated if true
>> + *
>> + * Allocate IRQ numbers and initialized all data structures to support
>> + * hiearchy IRQ domains.
>> + * Parameter @realloc is mainly to support legacy IRQs.
>> + * Returns error code or allocated IRQ number
>> + */
>> +int __irq_domain_alloc_irqs(struct irq_domain *domain, int irq_base,
>> +			    unsigned int nr_irqs, int node, void *arg,
>> +			    bool realloc)
>> +{
>> +	int i, ret, virq;
>> +
>> +	if (domain == NULL) {
>> +		domain = irq_default_domain;
>> +		if (WARN(!domain, "domain is NULL; cannot allocate IRQ\n"))
>> +			return -EINVAL;
>> +	}
>> +
>> +	if (!domain->ops->alloc) {
>> +		pr_debug("domain->ops->alloc() is NULL\n");
>> +		return -ENOSYS;
>> +	}
>> +
>> +	if (realloc && irq_base >= 0) {
>> +		virq = irq_base;
>> +	} else {
>> +		virq = irq_domain_alloc_descs(irq_base, nr_irqs, 0, node);
>> +		if (virq < 0) {
>> +			pr_debug("cannot allocate IRQ(base %d, count %d)\n",
>> +				 irq_base, nr_irqs);
>> +			return virq;
>> +		}
>> +	}
>> +
>> +	if (irq_domain_alloc_irq_data(domain, virq, nr_irqs)) {
>> +		pr_debug("cannot allocate memory for IRQ%d\n", virq);
>> +		ret = -ENOMEM;
>> +		goto out_free_desc;
>> +	}
>> +
>> +	mutex_lock(&irq_domain_mutex);
>> +	ret = domain->ops->alloc(domain, virq, nr_irqs, arg);
> 
> I've been through your patches and noticed that the only domain which does not
> call irq_domain_alloc_irqs_parent() is x86_vector_domain. And this makes sense
> *if* we already knew which domain is the nearest one to the CPU.
> But I don't think a well implemented device driver should assume itself be in
> a particular position of the interrupt delivery path.
> Actually it should be guaranteed by the core infrastructure that all the domains
> in the interrupt delivery path should allocate a hardware interrupt for the
> interrupt source.
> 
>> +	if (ret < 0) {
>> +		mutex_unlock(&irq_domain_mutex);
>> +		goto out_free_irq_data;
>> +	}
>> +	for (i = 0; i < nr_irqs; i++)
>> +		irq_domain_insert_irq(virq + i);
>> +	mutex_unlock(&irq_domain_mutex);
>> +
>> +	return virq;
>> +
>> +out_free_irq_data:
>> +	irq_domain_free_irq_data(virq, nr_irqs);
>> +out_free_desc:
>> +	irq_domain_free_descs(virq, nr_irqs);
>> +	return ret;
>> +}
>> +
> 
> 
> And besides the comments/questions I mentioned above, I am also curious about
> how the chained interrupts been processed.
> 
> Let's take a 3-level-chained-domains for example.
> Given 3 interrupt controllers A, B and C, and the interrupt delivery path is:
> 
> DEV -> A -> B -> C -> CPU
> 
> After the hierarchy irqdomains are established, the unique linux interrupt of
> DEV will be mapped with a hardware interrupt in each domain:
> 
> DomainA: HWIRQ_A => VIRQ_DEV
> DomainB: HWIRQ_B => VIRQ_DEV
> DomainC: HWIRQ_C => VIRQ_DEV
> 
> When the DEV triggered an interrupt signal, the CPU will acknowledge HWIRQ_C,
> and then irq_find_mapping(DomainC, HWIRQ_C) will be called to get the linux
> interrupt VIRQ_DEV, and after the handler of the VIRQ_DEV has been processed,
> the interrupt will end with the level (if have) uncleared on B, which will
> result in the interrupt of DEV cannot be processed again.
> 
> Or is there anything I misunderstand?
> 
> Thanks,
> Abel.
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
>