Message ID | 558D10E1.8040701@arm.com |
---|---|
State | New |
Headers | show |
Hi Marc: 在 2015/6/26 16:44, Marc Zyngier 写道: > > You can then keep your MBI stuff in a separate file, and call into > its_msi_prepare. > Thanks for your good suggestion! I have two questions: Question 1: I found the ‘its_msi_preapare ' defined without static. So,I guess you mean I can call this fucntion directly from mbigen driver, right? or I need make the code likes below and leave these code in ITS? static struct mbigen_domain_ops its_mbigen_ops = { + .mbigen_prepare = its_msi_prepare, }; static struct mbigen_domain_info its_mbigen_domain_info = { .ops = &its_mbigen_ops, }; Question 2: @@ -1489,6 +1538,18 @@ static int its_probe(struct device_node *node, struct irq_domain *parent) err = of_pci_msi_chip_add(&its->msi_chip); if (err) goto out_free_domains; + + if (IS_ENABLED(CONFIG_MBIGEN_IRQ_DOMAIN)) { + its->mbi_chip.domain = its_mbigen_create_irq_domain(node, + &its_mbigen_domain_info, + its->domain); + + if (!its->mbi_chip.domain) { + err = -ENOMEM; + pr_warn_once("ITS:no mbigen chip found\n"); + goto out_free_mbigen; + } + } } spin_lock(&its_lock); @@ -1497,6 +1558,9 @@ static int its_probe(struct device_node *node, struct irq_domain *parent) return 0; +out_free_mbigen: + if (its->mbi_chip.domain) + irq_domain_remove(its->mbi_chip.domain); out_free_domains: if (its->msi_chip.domain) irq_domain_remove(its->msi_chip.domain); What's you opinion about the code above Leave it in ITS or create the mbi irq domain in mbigen driver? If I have to create mbi irq domain in mbigen driver, I need a pointer of its domain. For this problem, I think i can solve it by using its_nodes’ in mbigen driver *if* [1] add a member " struct device_node *node" in 'struct its_node' [2] in 'its_probe' function , add its->node = node; [3] remove the static definition from 'static LIST_HEAD(its_nodes);' How is you opinion? Thansks again! >> Now, all these functions and data structure are defined as static. >> to use them, I have to remove the 'static' definition and put them >> in a head file ( create a new head file). > > I don't want to see these functions and structure leaking out of the > ITS code unless we're absolutely forced to do so. The above code > shows you one possible way to solve the problem. >
On 26/06/15 11:28, majun (F) wrote: > > Hi Marc: > > 在 2015/6/26 16:44, Marc Zyngier 写道: >> >> You can then keep your MBI stuff in a separate file, and call into >> its_msi_prepare. >> > Thanks for your good suggestion! > I have two questions: > > Question 1: > > I found the ‘its_msi_preapare ' defined without static. > So,I guess you mean I can call this fucntion directly > from mbigen driver, right? Yes. You can use it as part of your own msi_prepare function. > or I need make the code likes below and leave these code in ITS? > > static struct mbigen_domain_ops its_mbigen_ops = { > + .mbigen_prepare = its_msi_prepare, > }; This structure does not exist. Use the normal msi_domain_ops structure. > > static struct mbigen_domain_info its_mbigen_domain_info = { > .ops = &its_mbigen_ops, > }; > > Question 2: > > @@ -1489,6 +1538,18 @@ static int its_probe(struct device_node *node, struct irq_domain *parent) > err = of_pci_msi_chip_add(&its->msi_chip); > if (err) > goto out_free_domains; > + > + if (IS_ENABLED(CONFIG_MBIGEN_IRQ_DOMAIN)) { > + its->mbi_chip.domain = its_mbigen_create_irq_domain(node, > + &its_mbigen_domain_info, > + its->domain); > + > + if (!its->mbi_chip.domain) { > + err = -ENOMEM; > + pr_warn_once("ITS:no mbigen chip found\n"); > + goto out_free_mbigen; > + } > + } > } > > spin_lock(&its_lock); > @@ -1497,6 +1558,9 @@ static int its_probe(struct device_node *node, struct irq_domain *parent) > > return 0; > > +out_free_mbigen: > + if (its->mbi_chip.domain) > + irq_domain_remove(its->mbi_chip.domain); > out_free_domains: > if (its->msi_chip.domain) > irq_domain_remove(its->msi_chip.domain); > > What's you opinion about the code above > Leave it in ITS or create the mbi irq domain in mbigen driver? > If I have to create mbi irq domain in mbigen driver, > I need a pointer of its domain. > > For this problem, I think i can solve it by using its_nodes’ > in mbigen driver *if* > [1] add a member " struct device_node *node" in 'struct its_node' > [2] in 'its_probe' function , add > its->node = node; > [3] remove the static definition from 'static LIST_HEAD(its_nodes);' > > How is you opinion? My opinion is that we need to be able to lookup the domain from the core code without any of these hacks, and this is what I'm working on at the moment. There is no way external code will be allowed to mess with the internals of the ITS. For the time being, just expose the domain with a helper (you can match it with the of_node). In the long run, you should be able to look it up directly from the domain list. Thanks, M.
在 2015/6/26 18:40, Marc Zyngier 写道: > > My opinion is that we need to be able to lookup the domain from the core > code without any of these hacks, and this is what I'm working on at the > moment. There is no way external code will be allowed to mess with the > internals of the ITS. > > For the time being, just expose the domain with a helper (you can match > it with the of_node). Do you mean add a fucntion in ITS likes below: struct irq_domain *get_its_domain(struct device_node *node) { struct its_node *its = NULL; list_for_each_entry(its, &its_nodes, entry) { if(its->msi_chip.of_node == node) break; } return (its)?its->domain:NULL; } How about add a '.match ' member in its_domain_ops just like: .match = get_its_domain; So, I can use the fucntion 'irq_find_host' in mbigne driver >In the long run, you should be able to look it up > directly from the domain list. > I think the domain list you said is 'irq_domain_list' which defined in Irqdomain.c static LIST_HEAD(irq_domain_list); Thanks!
On 26/06/15 13:04, majun (F) wrote: > > > 在 2015/6/26 18:40, Marc Zyngier 写道: >> >> My opinion is that we need to be able to lookup the domain from the core >> code without any of these hacks, and this is what I'm working on at the >> moment. There is no way external code will be allowed to mess with the >> internals of the ITS. >> >> For the time being, just expose the domain with a helper (you can match >> it with the of_node). > Do you mean add a fucntion in ITS likes below: > > struct irq_domain *get_its_domain(struct device_node *node) > { > struct its_node *its = NULL; > > list_for_each_entry(its, &its_nodes, entry) { > if(its->msi_chip.of_node == node) > break; > } > > return (its)?its->domain:NULL; > } Yes. > > How about add a '.match ' member in its_domain_ops > just like: > .match = get_its_domain; > > So, I can use the fucntion 'irq_find_host' in mbigne driver And that will only return the PCI/MSI domain, which is not of any help to you. At the moment, we register the PCI/MSI domain with the the of_node of the ITS so that a PCI controller can match the its MSI controller, and the ITS domain is completely anonymous (it doesn't have an of_node). What I'm working on is a way to distinguish between several domains that are identified by the same of_node, but cater for different bus types. The current match function doesn't quite work for that case. Thanks, M.
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 1b7e155..9a68c77 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -1200,49 +1200,54 @@ static int its_get_pci_alias(struct pci_dev *pdev, u16 alias, void *data) return 0; } -static int its_msi_prepare(struct irq_domain *domain, struct device *dev, - int nvec, msi_alloc_info_t *info) +int its_msi_prepare(struct irq_domain *domain, u32 dev_id, + int nvec, msi_alloc_info_t *info) { - struct pci_dev *pdev; struct its_node *its; struct its_device *its_dev; - struct its_pci_alias dev_alias; - if (!dev_is_pci(dev)) - return -EINVAL; - - pdev = to_pci_dev(dev); - dev_alias.pdev = pdev; - dev_alias.count = nvec; - - pci_for_each_dma_alias(pdev, its_get_pci_alias, &dev_alias); its = domain->parent->host_data; - - its_dev = its_find_device(its, dev_alias.dev_id); + its_dev = its_find_device(its, dev_id); if (its_dev) { /* * We already have seen this ID, probably through * another alias (PCI bridge of some sort). No need to * create the device. */ - dev_dbg(dev, "Reusing ITT for devID %x\n", dev_alias.dev_id); + pr_debug("Reusing ITT for devID %x\n", dev_id); goto out; } - its_dev = its_create_device(its, dev_alias.dev_id, dev_alias.count); + its_dev = its_create_device(its, dev_id, nvec); if (!its_dev) return -ENOMEM; - dev_dbg(&pdev->dev, "ITT %d entries, %d bits\n", - dev_alias.count, ilog2(dev_alias.count)); + pr_debug("ITT %d entries, %d bits\n", nvec, ilog2(nvec)); out: info->scratchpad[0].ptr = its_dev; - info->scratchpad[1].ptr = dev; return 0; } +static int its_pci_msi_prepare(struct irq_domain *domain, struct device *dev, + int nvec, msi_alloc_info_t *info) +{ + struct pci_dev *pdev; + struct its_pci_alias dev_alias; + + if (!dev_is_pci(dev)) + return -EINVAL; + + pdev = to_pci_dev(dev); + dev_alias.pdev = pdev; + dev_alias.count = nvec; + + pci_for_each_dma_alias(pdev, its_get_pci_alias, &dev_alias); + + return its_msi_prepare(domain, dev_alias.dev_id, dev_alias.count, info); +} + static struct msi_domain_ops its_pci_msi_ops = { - .msi_prepare = its_msi_prepare, + .msi_prepare = its_pci_msi_prepare, }; static struct msi_domain_info its_pci_msi_domain_info = { @@ -1287,8 +1292,9 @@ static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq, &its_irq_chip, its_dev); - dev_dbg(info->scratchpad[1].ptr, "ID:%d pID:%d vID:%d\n", - (int)(hwirq - its_dev->lpi_base), (int)hwirq, virq + i); + pr_debug("ID:%d pID:%d vID:%d\n", + (int)(hwirq - its_dev->lpi_base), + (int)hwirq, virq + i); } return 0;