mbigen的domain匹配

在mbigen_device_probe->mbigen_acpi_create_domain->platform_msi_create_device_domain
    domain = platform_msi_create_device_domain(&pdev->dev, num_msis,
                           mbigen_write_msg,
                           &mbigen_domain_ops,
                           mgn_chip);

注意在调用platform_msi_create_device_domain 的时候会传递一个mbigen_domain_ops
static struct irq_domain_ops mbigen_domain_ops = {
    .translate    = mbigen_domain_translate,
    .alloc        = mbigen_irq_domain_alloc,
    .free        = irq_domain_free_irqs_common,
};
随后platform_msi_create_device_domain->irq_domain_create_hierarchy->irq_domain_create_linear->__irq_domain_add
struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, int size,
                    irq_hw_number_t hwirq_max, int direct_max,
                    const struct irq_domain_ops *ops,
                    void *host_data)
{
    struct device_node *of_node = to_of_node(fwnode);
    struct irq_domain *domain;

    domain = kzalloc_node(sizeof(*domain) + (sizeof(unsigned int) * size),
                  GFP_KERNEL, of_node_to_nid(of_node));
    if (WARN_ON(!domain))
        return NULL;

    of_node_get(of_node);

    /* Fill structure */
    INIT_RADIX_TREE(&domain->revmap_tree, GFP_KERNEL);
    domain->ops = ops;
    domain->host_data = host_data;
    domain->fwnode = fwnode;
    domain->hwirq_max = hwirq_max;
    domain->revmap_size = size;
    domain->revmap_direct_max_irq = direct_max;
    irq_domain_check_hierarchy(domain);

    mutex_lock(&irq_domain_mutex);
    list_add(&domain->link, &irq_domain_list);
    mutex_unlock(&irq_domain_mutex);

    pr_debug("Added domain %s\n", domain->name);
    return domain;
}
在__irq_domain_add 中我们会初始化一个irq_domain *domain,并将其添加到irq_domain_list,而irq_domain_list是一个全局的静态list.总结一下mbigen 这个模块走的最重要的事情就是初始化了一个irq_domain而已
那irq_domain_list 中应该包含很多domain,设备具体要用哪一个domain是在哪里决定的呢?
以下面的函数为例
int acpi_register_gsi(struct device *dev, u32 gsi, int trigger,
              int polarity)
{
    struct irq_fwspec fwspec;
    struct acpi_device *adev = dev ? to_acpi_device(dev) : NULL;

    if (adev && is_acpi_device_node(&adev->fwnode) &&
        adev->interrupt_producer)
        /* devices in DSDT connecting to spefic interrupt producer */
        fwspec.fwnode = adev->interrupt_producer;
    else if (acpi_gsi_domain_id)
        /* devices connecting to gicd in default */
        fwspec.fwnode = acpi_gsi_domain_id;
    else {
        pr_warn("GSI: No registered irqchip, giving up\n");
        return -EINVAL;
    }

    fwspec.param[0] = gsi;
    fwspec.param[1] = acpi_dev_get_irq_type(trigger, polarity);
    fwspec.param_count = 2;

    return irq_create_fwspec_mapping(&fwspec);
}
acpi_register_gsi 中初始化了一个irq_fwspec。
unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)
{
    struct irq_domain *domain;
    struct irq_data *irq_data;
    irq_hw_number_t hwirq;
    unsigned int type = IRQ_TYPE_NONE;
    int virq;

    if (fwspec->fwnode) {
        domain = irq_find_matching_fwspec(fwspec, DOMAIN_BUS_WIRED);
        if (!domain)
            domain = irq_find_matching_fwspec(fwspec, DOMAIN_BUS_ANY);
    } else {
        domain = irq_default_domain;
    }
}
由于fwspec->fwnode 肯定不为NULL,因此调用irq_find_matching_fwspec
struct irq_domain *irq_find_matching_fwspec(struct irq_fwspec *fwspec,
                        enum irq_domain_bus_token bus_token)
{
    struct irq_domain *h, *found = NULL;
    struct fwnode_handle *fwnode = fwspec->fwnode;
    int rc;

    /* We might want to match the legacy controller last since
     * it might potentially be set to match all interrupts in
     * the absence of a device node. This isn't a problem so far
     * yet though...
     *
     * bus_token == DOMAIN_BUS_ANY matches any domain, any other
     * values must generate an exact match for the domain to be
     * selected.
     */
    mutex_lock(&irq_domain_mutex);
    list_for_each_entry(h, &irq_domain_list, link) {
        if (h->ops->select && fwspec->param_count)
            rc = h->ops->select(h, fwspec, bus_token);
        else if (h->ops->match)
            rc = h->ops->match(h, to_of_node(fwnode), bus_token);
        else
            rc = ((fwnode != NULL) && (h->fwnode == fwnode) &&
                  ((bus_token == DOMAIN_BUS_ANY) ||
                   (h->bus_token == bus_token)));

        if (rc) {
            found = h;
            break;
        }
    }
    mutex_unlock(&irq_domain_mutex);
    return found;
}
在irq_find_matching_fwspec 中我们以mbigen的struct irq_domain_ops mbigen_domain_ops为例,由于mbigen_domain_ops为例的select和match函数为NULL,因此在irq_find_matching_fwspec走最后的else。由于在mbigen中初始化domain的时候并没有定义bus_token,因此h->bus_token=0,而irq_create_fwspec_mapping 中bus_token==DOMAIN_BUS_WIRED,因此else的条件也就不满足。因此如果要使用mbigen这个domain除了硬件要挂在mbigen下面外,其bus_token 应该要等于DOMAIN_BUS_ANY

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值