From: majun258@huawei.com (majun (F))
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v3 1/3] IRQ/Gic-V3: Add mbigen driver to support mbigen interrupt controller
Date: Wed, 8 Jul 2015 12:21:04 +0800 [thread overview]
Message-ID: <559CA530.2090508@huawei.com> (raw)
In-Reply-To: <alpine.DEB.2.11.1507061248090.3916@nanos>
Hi Thomas:
? 2015/7/6 20:33, Thomas Gleixner ??:
> On Mon, 6 Jul 2015, Ma Jun wrote:
>
>> +/**
>> + * get_mbigen_node_type: get the mbigen node type
>> + * @nid: the mbigen node value
>> + * return 0: evnent id of interrupt connected to this node can be changed.
>> + * return 1: evnent id of interrupt connected to this node cant be changed.
>> + */
>> +static int get_mbigen_node_type(int nid)
>> +{
>> + if (nid > MG_NR) {
>> + pr_warn("MBIGEN: Device ID exceeds max number!\n");
>> + return 1;
>> + }
>> + if ((nid == 0) || (nid == 5) || (nid > 7))
>> + return 0;
>> + else
>> + return 1;
>
> Oh no. We do not hardcode such properties into a driver. That wants to
> be in the device tree and set as a property in the node data structure.
>
Ok,I will move this to device tree
>> +static int mbigen_write_msg(struct irq_data *d, struct msi_msg *msg)
>> +{
>> + struct mbigen_chip *chip = d->domain->host_data;
>> + void __iomem *addr;
>> + u32 nid, val, offset;
>> + int ret = 0;
>> +
>> + nid = GET_NODE_NUM(d->hwirq);
>> + ret = get_mbigen_node_type(nid);
>> + if (ret)
>> + return 0;
>
> Care to explain what this does? It seems for some nodes you cannot
> write the msi message. So how is that supposed to work? How is that
> interrupt controlled (mask/unmask ...) ?
>
This function is used to write irq event id into vector register.Depends on
hardware design, write operation is permitted in some mbigen node(nid=0,5,and >7),
For other mbigen node, this register is read only.
But only vector register has this problem. Other registers are ok for read/write.
>> +
>> + ofst = hwirq / 32 * 4;
>> + mask = 1 << (hwirq % 32);
>> +
>> + addr = chip->base + MBIGEN_TYPE_REG_ADDR(nid, ofst);
>> + raw_spin_lock(&chip->lock);
>> + val = readl_relaxed(addr);
>> +
>> + if (type == IRQ_TYPE_LEVEL_HIGH)
>> + val |= mask;
>> + else if (type == IRQ_TYPE_EDGE_RISING)
>> + val &= ~mask;
>> +
>> + writel_relaxed(val, addr);
>> + raw_spin_unlock(&chip->lock);
>
> What is the lock protecting here? The read/write access to a per
> interrupt register? Why is the per interrupt descriptor lock not
> sufficient and why does the above write_msg not requited locking?
>
yes,lock protecting is not necessary here.
>> + return 0;
[...]
>> +static int mbigen_domain_alloc(struct irq_domain *domain, unsigned int virq,
>> + unsigned int nr_irqs, void *arg)
>> +{
>> + struct mbigen_chip *chip = domain->host_data;
>> + struct of_phandle_args *irq_data = arg;
>> + irq_hw_number_t hwirq;
>> + u32 nid, dev_id, mbi_lines;
>> + struct mbigen_node *mgn_node;
>> + struct mbigen_device *mgn_dev;
>> + msi_alloc_info_t out_arg;
>> + int ret = 0, i;
>> +
>> + /* OF style allocation, one interrupt at a time */
>
> -ENOPARSE
>
what's this mean? I didn't find this definition in kernel code
>> + WARN_ON(nr_irqs != 1);
>> +
>> + dev_id = irq_data->args[0];
>> + nid = irq_data->args[3];
>> + hwirq = COMPOSE_HWIRQ(nid, irq_data->args[2]);
>> +
>> + mgn_node = get_mbigen_node(chip, nid);
>> + if (!mgn_node)
>> + return -ENODEV;
>> +
>> + mgn_dev = mbigen_create_device(mgn_node, irq_data->np, virq, nr_irqs);
>> + if (!mgn_dev)
>> + return -ENOMEM;
>
> Leaks the node allocation.
>
>> +
>> + mbi_lines = irq_data->args[1];
>> +
>> + ret = its_msi_prepare(domain, dev_id, mbi_lines, &out_arg);
>
> This looks wrong. Why do you have an explicit call for this in the
> allocation function?
>
> msi_domain_ops.msi_prepare is called from the core code and you should
> provide a msi_prepare callback which does the necessary initialization
> and invokes the parent domains msi_prepare callback.
>
According to Marc suggestion, I changed the ITS code so I can use its_msi_prepare
function in my code.
So,do you mean i should not call this function directly ?
How about make this code likes below in mbigen driver:
static struct msi_domain_ops mbigen_domain_ops = {
.msi_prepare = mbigen_domain_ops_prepare,
};
static int mbigen_domain_ops_prepare(struct irq_domain *domain, struct device *dev,
int nvec, msi_alloc_info_t *info)
{
return its_msi_prepare(domain, dev_id, count, info);
}
>> + if (ret)
>> + return ret;
>
> Leaks the node allocation and the device.
>
>> +
>> + ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &out_arg);
>> + if (ret < 0)
>> + return ret;
>> +
>> + for (i = 0; i < nr_irqs; i++) {
>
> This loop is required because?
>
Although we know this value is 1, I think use loop seems better
>> + irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
>> + &mbigen_irq_chip, mgn_dev);
>> + }
>> +
>> + return ret;
>
>> +/*
>> + * Early initialization as an interrupt controller
>> + */
>> +static int __init mbigen_of_init(struct device_node *node,
>> + struct device_node *parent_node)
>> +{
>> + struct mbigen_chip *chip;
>> + struct irq_domain *parent_domain;
>> + int err;
>> +
>> + parent_node = of_parse_phandle(node, "msi-parent", 0);
>
> Huch. parent node is an argument here. So WHY do you need to override
> it with some magic parent entry in the mbigen node? Seems your
> devicetree design sucks.
Because parent_nod argument point to gic node, but the parent device node of
mbigen is its node.
I didn't find the way how to pass its node into this function as the parent_node,
would you please give me some hint?
Thanks
>
>> diff --git a/include/linux/mbi.h b/include/linux/mbi.h
>> new file mode 100644
>> index 0000000..d3b8155
>> --- /dev/null
>> +++ b/include/linux/mbi.h
>> +
>> +/* Function to parse and map message interrupts */
>> +extern int its_msi_prepare(struct irq_domain *domain, u32 dev_id,
>> + int nvec, msi_alloc_info_t *info);
>> +extern struct irq_domain *get_its_domain(struct device_node *node);
>
> Crap in various aspects
>
> - these functions should only be visible from drivers/irqchip/
>
> - the header name is wrong as it does not provide any MBI
> specific functionality
>
Maybe I can named this file as 'arm-gic-v3-its.h' and put it in
include/linux/irqchip/
Thanks
WARNING: multiple messages have this Message-ID (diff)
From: "majun (F)" <majun258@huawei.com>
To: Thomas Gleixner <tglx@linutronix.de>
Cc: <Catalin.Marinas@arm.com>, <linux-kernel@vger.kernel.org>,
<linux-arm-kernel@lists.infradead.org>, <Will.Deacon@arm.com>,
<mark.rutland@arm.com>, <marc.zyngier@arm.com>,
<jason@lakedaemon.net>, <lizefan@huawei.com>,
<huxinwei@huawei.com>, <dingtianhong@huawei.com>,
<zhaojunhua@hisilicon.com>, <liguozhu@hisilicon.com>,
<xuwei5@hisilicon.com>, <wei.chenwei@hisilicon.com>,
<guohanjun@huawei.com>, <wuyun.wu@huawei.com>,
<guodong.xu@linaro.org>, <haojian.zhuang@linaro.org>,
<zhangfei.gao@linaro.org>, <usman.ahmad@linaro.org>
Subject: Re: [PATCH v3 1/3] IRQ/Gic-V3: Add mbigen driver to support mbigen interrupt controller
Date: Wed, 8 Jul 2015 12:21:04 +0800 [thread overview]
Message-ID: <559CA530.2090508@huawei.com> (raw)
In-Reply-To: <alpine.DEB.2.11.1507061248090.3916@nanos>
Hi Thomas:
在 2015/7/6 20:33, Thomas Gleixner 写道:
> On Mon, 6 Jul 2015, Ma Jun wrote:
>
>> +/**
>> + * get_mbigen_node_type: get the mbigen node type
>> + * @nid: the mbigen node value
>> + * return 0: evnent id of interrupt connected to this node can be changed.
>> + * return 1: evnent id of interrupt connected to this node cant be changed.
>> + */
>> +static int get_mbigen_node_type(int nid)
>> +{
>> + if (nid > MG_NR) {
>> + pr_warn("MBIGEN: Device ID exceeds max number!\n");
>> + return 1;
>> + }
>> + if ((nid == 0) || (nid == 5) || (nid > 7))
>> + return 0;
>> + else
>> + return 1;
>
> Oh no. We do not hardcode such properties into a driver. That wants to
> be in the device tree and set as a property in the node data structure.
>
Ok,I will move this to device tree
>> +static int mbigen_write_msg(struct irq_data *d, struct msi_msg *msg)
>> +{
>> + struct mbigen_chip *chip = d->domain->host_data;
>> + void __iomem *addr;
>> + u32 nid, val, offset;
>> + int ret = 0;
>> +
>> + nid = GET_NODE_NUM(d->hwirq);
>> + ret = get_mbigen_node_type(nid);
>> + if (ret)
>> + return 0;
>
> Care to explain what this does? It seems for some nodes you cannot
> write the msi message. So how is that supposed to work? How is that
> interrupt controlled (mask/unmask ...) ?
>
This function is used to write irq event id into vector register.Depends on
hardware design, write operation is permitted in some mbigen node(nid=0,5,and >7),
For other mbigen node, this register is read only.
But only vector register has this problem. Other registers are ok for read/write.
>> +
>> + ofst = hwirq / 32 * 4;
>> + mask = 1 << (hwirq % 32);
>> +
>> + addr = chip->base + MBIGEN_TYPE_REG_ADDR(nid, ofst);
>> + raw_spin_lock(&chip->lock);
>> + val = readl_relaxed(addr);
>> +
>> + if (type == IRQ_TYPE_LEVEL_HIGH)
>> + val |= mask;
>> + else if (type == IRQ_TYPE_EDGE_RISING)
>> + val &= ~mask;
>> +
>> + writel_relaxed(val, addr);
>> + raw_spin_unlock(&chip->lock);
>
> What is the lock protecting here? The read/write access to a per
> interrupt register? Why is the per interrupt descriptor lock not
> sufficient and why does the above write_msg not requited locking?
>
yes,lock protecting is not necessary here.
>> + return 0;
[...]
>> +static int mbigen_domain_alloc(struct irq_domain *domain, unsigned int virq,
>> + unsigned int nr_irqs, void *arg)
>> +{
>> + struct mbigen_chip *chip = domain->host_data;
>> + struct of_phandle_args *irq_data = arg;
>> + irq_hw_number_t hwirq;
>> + u32 nid, dev_id, mbi_lines;
>> + struct mbigen_node *mgn_node;
>> + struct mbigen_device *mgn_dev;
>> + msi_alloc_info_t out_arg;
>> + int ret = 0, i;
>> +
>> + /* OF style allocation, one interrupt at a time */
>
> -ENOPARSE
>
what's this mean? I didn't find this definition in kernel code
>> + WARN_ON(nr_irqs != 1);
>> +
>> + dev_id = irq_data->args[0];
>> + nid = irq_data->args[3];
>> + hwirq = COMPOSE_HWIRQ(nid, irq_data->args[2]);
>> +
>> + mgn_node = get_mbigen_node(chip, nid);
>> + if (!mgn_node)
>> + return -ENODEV;
>> +
>> + mgn_dev = mbigen_create_device(mgn_node, irq_data->np, virq, nr_irqs);
>> + if (!mgn_dev)
>> + return -ENOMEM;
>
> Leaks the node allocation.
>
>> +
>> + mbi_lines = irq_data->args[1];
>> +
>> + ret = its_msi_prepare(domain, dev_id, mbi_lines, &out_arg);
>
> This looks wrong. Why do you have an explicit call for this in the
> allocation function?
>
> msi_domain_ops.msi_prepare is called from the core code and you should
> provide a msi_prepare callback which does the necessary initialization
> and invokes the parent domains msi_prepare callback.
>
According to Marc suggestion, I changed the ITS code so I can use its_msi_prepare
function in my code.
So,do you mean i should not call this function directly ?
How about make this code likes below in mbigen driver:
static struct msi_domain_ops mbigen_domain_ops = {
.msi_prepare = mbigen_domain_ops_prepare,
};
static int mbigen_domain_ops_prepare(struct irq_domain *domain, struct device *dev,
int nvec, msi_alloc_info_t *info)
{
return its_msi_prepare(domain, dev_id, count, info);
}
>> + if (ret)
>> + return ret;
>
> Leaks the node allocation and the device.
>
>> +
>> + ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &out_arg);
>> + if (ret < 0)
>> + return ret;
>> +
>> + for (i = 0; i < nr_irqs; i++) {
>
> This loop is required because?
>
Although we know this value is 1, I think use loop seems better
>> + irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
>> + &mbigen_irq_chip, mgn_dev);
>> + }
>> +
>> + return ret;
>
>> +/*
>> + * Early initialization as an interrupt controller
>> + */
>> +static int __init mbigen_of_init(struct device_node *node,
>> + struct device_node *parent_node)
>> +{
>> + struct mbigen_chip *chip;
>> + struct irq_domain *parent_domain;
>> + int err;
>> +
>> + parent_node = of_parse_phandle(node, "msi-parent", 0);
>
> Huch. parent node is an argument here. So WHY do you need to override
> it with some magic parent entry in the mbigen node? Seems your
> devicetree design sucks.
Because parent_nod argument point to gic node, but the parent device node of
mbigen is its node.
I didn't find the way how to pass its node into this function as the parent_node,
would you please give me some hint?
Thanks
>
>> diff --git a/include/linux/mbi.h b/include/linux/mbi.h
>> new file mode 100644
>> index 0000000..d3b8155
>> --- /dev/null
>> +++ b/include/linux/mbi.h
>> +
>> +/* Function to parse and map message interrupts */
>> +extern int its_msi_prepare(struct irq_domain *domain, u32 dev_id,
>> + int nvec, msi_alloc_info_t *info);
>> +extern struct irq_domain *get_its_domain(struct device_node *node);
>
> Crap in various aspects
>
> - these functions should only be visible from drivers/irqchip/
>
> - the header name is wrong as it does not provide any MBI
> specific functionality
>
Maybe I can named this file as 'arm-gic-v3-its.h' and put it in
include/linux/irqchip/
Thanks
next prev parent reply other threads:[~2015-07-08 4:21 UTC|newest]
Thread overview: 46+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-07-06 7:09 [PATCH v3 0/3] IRQ/Gic-V3:Support Mbigen interrupt controller Ma Jun
2015-07-06 7:09 ` Ma Jun
2015-07-06 7:09 ` [PATCH v3 1/3] IRQ/Gic-V3: Add mbigen driver to support mbigen " Ma Jun
2015-07-06 7:09 ` Ma Jun
2015-07-06 12:33 ` Thomas Gleixner
2015-07-06 12:33 ` Thomas Gleixner
2015-07-08 4:21 ` majun (F) [this message]
2015-07-08 4:21 ` majun (F)
2015-07-08 10:44 ` Thomas Gleixner
2015-07-08 10:44 ` Thomas Gleixner
2015-07-16 8:35 ` majun (F)
2015-07-16 8:35 ` majun (F)
2015-07-08 15:16 ` Marc Zyngier
2015-07-08 15:16 ` Marc Zyngier
2015-07-16 8:35 ` majun (F)
2015-07-16 8:35 ` majun (F)
2015-07-16 8:52 ` Marc Zyngier
2015-07-16 8:52 ` Marc Zyngier
2015-07-16 9:22 ` majun (F)
2015-07-16 9:22 ` majun (F)
2015-07-16 9:30 ` Marc Zyngier
2015-07-16 9:30 ` Marc Zyngier
2015-07-16 12:26 ` majun (F)
2015-07-16 12:26 ` majun (F)
2015-07-16 13:37 ` Marc Zyngier
2015-07-16 13:37 ` Marc Zyngier
2015-07-27 2:25 ` majun (F)
2015-07-27 2:25 ` majun (F)
2015-07-08 15:30 ` Marc Zyngier
2015-07-08 15:30 ` Marc Zyngier
2015-07-16 8:35 ` majun (F)
2015-07-16 8:35 ` majun (F)
2015-07-06 7:09 ` [PATCH v3 2/3] IRQ/Gic-V3: Change arm-gic-its to support the Mbigen interrupt Ma Jun
2015-07-06 7:09 ` Ma Jun
2015-07-06 7:09 ` [PATCH v3 3/3] dt-binding:Documents the mbigen bindings Ma Jun
2015-07-06 7:09 ` Ma Jun
2015-07-08 13:40 ` Mark Rutland
2015-07-08 13:40 ` Mark Rutland
2015-07-08 14:01 ` Marc Zyngier
2015-07-08 14:01 ` Marc Zyngier
2015-07-16 8:35 ` majun (F)
2015-07-16 8:35 ` majun (F)
2015-07-20 16:38 ` Mark Rutland
2015-07-20 16:38 ` Mark Rutland
2015-07-25 3:03 ` majun (F)
2015-07-25 3:03 ` majun (F)
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=559CA530.2090508@huawei.com \
--to=majun258@huawei.com \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.