diff --git "a/linux/\345\206\205\346\240\270-\351\251\261\345\212\250/\344\270\255\346\226\255/\347\241\254\344\270\255\346\226\255--\344\270\255\346\226\255\345\217\267\346\230\240\345\260\204.md" "b/linux/\345\206\205\346\240\270-\351\251\261\345\212\250/\344\270\255\346\226\255/\347\241\254\344\270\255\346\226\255--\344\270\255\346\226\255\345\217\267\346\230\240\345\260\204.md" index 81c3364..94730c1 100755 --- "a/linux/\345\206\205\346\240\270-\351\251\261\345\212\250/\344\270\255\346\226\255/\347\241\254\344\270\255\346\226\255--\344\270\255\346\226\255\345\217\267\346\230\240\345\260\204.md" +++ "b/linux/\345\206\205\346\240\270-\351\251\261\345\212\250/\344\270\255\346\226\255/\347\241\254\344\270\255\346\226\255--\344\270\255\346\226\255\345\217\267\346\230\240\345\260\204.md" @@ -208,4 +208,53 @@ unsigned int irq_create_mapping_affinity(struct irq_domain *domain, return virq; } EXPORT_SYMBOL_GPL(irq_create_mapping_affinity); + +int irq_domain_associate(struct irq_domain *domain, unsigned int virq, + irq_hw_number_t hwirq) +{ + struct irq_data *irq_data = irq_get_irq_data(virq); + int ret; + + if (WARN(hwirq >= domain->hwirq_max, + "error: hwirq 0x%x is too large for %s\n", (int)hwirq, domain->name)) + return -EINVAL; + if (WARN(!irq_data, "error: virq%i is not allocated", virq)) + return -EINVAL; + if (WARN(irq_data->domain, "error: virq%i is already associated", virq)) + return -EINVAL; + + mutex_lock(&irq_domain_mutex); + irq_data->hwirq = hwirq; + irq_data->domain = domain; + if (domain->ops->map) { + ret = domain->ops->map(domain, virq, hwirq); + if (ret != 0) { + /* + * If map() returns -EPERM, this interrupt is protected + * by the firmware or some other service and shall not + * be mapped. Don't bother telling the user about it. + */ + if (ret != -EPERM) { + pr_info("%s didn't like hwirq-0x%lx to VIRQ%i mapping (rc=%d)\n", + domain->name, hwirq, virq, ret); + } + irq_data->domain = NULL; + irq_data->hwirq = 0; + mutex_unlock(&irq_domain_mutex); + return ret; + } + + /* If not already assigned, give the domain the chip's name */ + if (!domain->name && irq_data->chip) + domain->name = irq_data->chip->name; + } + + domain->mapcount++; + irq_domain_set_mapping(domain, hwirq, irq_data); + mutex_unlock(&irq_domain_mutex); + + irq_clear_status_flags(virq, IRQ_NOREQUEST); + + return 0; +} ``` \ No newline at end of file