On 2014/9/23 17:43, Joe.C wrote:
> On Mon, 2014-09-22 at 16:17 +0800, Jiang Liu wrote:
>> @@ -388,7 +389,6 @@ EXPORT_SYMBOL_GPL(irq_create_direct_mapping);
>>  unsigned int irq_create_mapping(struct irq_domain *domain,
>>                              irq_hw_number_t hwirq)
>>  {
>> -    unsigned int hint;
>>      int virq;
>>  
>>      pr_debug("irq_create_mapping(0x%p, 0x%lx)\n", domain, hwirq);
>> @@ -410,12 +410,8 @@ unsigned int irq_create_mapping(struct irq_domain 
>> *domain,
>>      }
>>  
>>      /* Allocate a virtual interrupt number */
>> -    hint = hwirq % nr_irqs;
>> -    if (hint == 0)
>> -            hint++;
>> -    virq = irq_alloc_desc_from(hint, of_node_to_nid(domain->of_node));
>> -    if (virq <= 0)
>> -            virq = irq_alloc_desc_from(1, of_node_to_nid(domain->of_node));
>> +    virq = irq_domain_alloc_descs(-1, 1, hwirq,
>> +                                  of_node_to_nid(domain->of_node));
> 
> If I read this correct, the resulting virq is different after your
> change.
It should have the same effect. We just factored out original code as
a function, so it could be reused.

> 
>>      if (virq <= 0) {
>>              pr_debug("-> virq allocation failed\n");
>>              return 0;
>> @@ -490,7 +486,10 @@ unsigned int irq_create_of_mapping(struct 
>> of_phandle_args *irq_data)
>>      }
>>  
>>      /* Create mapping */
>> -    virq = irq_create_mapping(domain, hwirq);
>> +    if (irq_domain_is_hierarchy(domain))
>> +            virq = irq_domain_alloc_irqs(domain, 1, NUMA_NO_NODE, irq_data);
>> +    else
>> +            virq = irq_create_mapping(domain, hwirq);
>>      if (!virq)
>>              return virq;
> 
> hwirq returned from xlat above is lost. Without hwirq or virq, how do we
> know which irq are we working for?
> Also, if the irq_desc/irq_data was already created, this will create
> another one. Should we do irq_find_mapping just like irq_create_mapping?
When irq_create_of_mapping is called, IRQ desc/irq_data haven't been
allocated yet. The parameter irq_data is type of struct of_phandle_args
instead of struct irq_data:)

We pass irq_data to irq_domain_alloc_irqs(), the we could reconstruct
hwirq from irq_data if needed.

To make the code clearer, I plan to change code as below:
unsigned int irq_create_of_mapping(struct of_phandle_args *irq_data)
{
        struct irq_domain *domain;
        irq_hw_number_t hwirq;
        unsigned int type = IRQ_TYPE_NONE;
        unsigned int virq;

        domain = irq_data->np ? irq_find_host(irq_data->np) :
irq_default_domain;
        if (!domain) {
                pr_warn("no irq domain found for %s !\n",
                        of_node_full_name(irq_data->np));
                return 0;
        }

+        if (irq_domain_is_hierarchy(domain))
+                return irq_domain_alloc_irqs(domain, 1, NUMA_NO_NODE,
irq_data);
+
        /* If domain has no translation, then we assume interrupt line */
        if (domain->ops->xlate == NULL)
                hwirq = irq_data->args[0];
        else {
                if (domain->ops->xlate(domain, irq_data->np, irq_data->args,
                                        irq_data->args_count, &hwirq,
&type))
                        return 0;
        }

        /* Create mapping */
        virq = irq_create_mapping(domain, hwirq);
        if (!virq)
                return virq;

        /* Set type if specified and different than the current one */
        if (type != IRQ_TYPE_NONE &&
            type != irq_get_trigger_type(virq))
                irq_set_irq_type(virq, type);
        return virq;
}
EXPORT_SYMBOL_GPL(irq_create_of_mapping);

>> +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;
>                          ^
> extra space here.
Will fix it in next version.
Thanks, Joe!
Gerry
> 
> Joe.C
> 
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to