* [PATCH RFC 1/7] platform-msi: Allow MSIs to be allocated in chunks
2015-10-15 15:39 [PATCH RFC 0/7] Adding core support for wire-MSI bridges Marc Zyngier
@ 2015-10-15 15:39 ` Marc Zyngier
2015-10-15 15:39 ` [PATCH RFC 2/7] platform-msi: Factor out allocation/free of private data Marc Zyngier
` (7 subsequent siblings)
8 siblings, 0 replies; 30+ messages in thread
From: Marc Zyngier @ 2015-10-15 15:39 UTC (permalink / raw)
To: Thomas Gleixner, Jiang Liu, Jason Cooper
Cc: Ma Jun, linux-arm-kernel, linux-pci, linux-kernel
MSIs for a given device are normally all allocated in one go.
Make sure the internal code can allocate them one at a time
if required.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
drivers/base/platform-msi.c | 32 ++++++++++++++++++++------------
1 file changed, 20 insertions(+), 12 deletions(-)
diff --git a/drivers/base/platform-msi.c b/drivers/base/platform-msi.c
index 5df4575..6148c78 100644
--- a/drivers/base/platform-msi.c
+++ b/drivers/base/platform-msi.c
@@ -25,6 +25,7 @@
#include <linux/slab.h>
#define DEV_ID_SHIFT 24
+#define MAX_DEV_MSIS (1 << (32 - DEV_ID_SHIFT))
/*
* Internal data structure containing a (made up, but unique) devid
@@ -110,13 +111,16 @@ static void platform_msi_update_chip_ops(struct msi_domain_info *info)
chip->irq_write_msi_msg = platform_msi_write_msg;
}
-static void platform_msi_free_descs(struct device *dev)
+static void platform_msi_free_descs(struct device *dev, int base, int nvec)
{
struct msi_desc *desc, *tmp;
list_for_each_entry_safe(desc, tmp, dev_to_msi_list(dev), list) {
- list_del(&desc->list);
- free_msi_entry(desc);
+ if (desc->platform.msi_index >= base &&
+ desc->platform.msi_index < (base + nvec)) {
+ list_del(&desc->list);
+ free_msi_entry(desc);
+ }
}
}
@@ -124,17 +128,22 @@ static int platform_msi_alloc_descs(struct device *dev, int nvec,
struct platform_msi_priv_data *data)
{
- int i;
+ struct msi_desc *desc;
+ int i, base = 0;
- for (i = 0; i < nvec; i++) {
- struct msi_desc *desc;
+ if (!list_empty(dev_to_msi_list(dev))) {
+ desc = list_last_entry(dev_to_msi_list(dev),
+ struct msi_desc, list);
+ base = desc->platform.msi_index + 1;
+ }
+ for (i = 0; i < nvec; i++) {
desc = alloc_msi_entry(dev);
if (!desc)
break;
desc->platform.msi_priv_data = data;
- desc->platform.msi_index = i;
+ desc->platform.msi_index = base + i;
desc->nvec_used = 1;
list_add_tail(&desc->list, dev_to_msi_list(dev));
@@ -142,7 +151,7 @@ static int platform_msi_alloc_descs(struct device *dev, int nvec,
if (i != nvec) {
/* Clean up the mess */
- platform_msi_free_descs(dev);
+ platform_msi_free_descs(dev, base, nvec);
return -ENOMEM;
}
@@ -201,8 +210,7 @@ int platform_msi_domain_alloc_irqs(struct device *dev, unsigned int nvec,
* accordingly (which would impact the max number of MSI
* capable devices).
*/
- if (!dev->msi_domain || !write_msi_msg || !nvec ||
- nvec > (1 << (32 - DEV_ID_SHIFT)))
+ if (!dev->msi_domain || !write_msi_msg || !nvec || nvec > MAX_DEV_MSIS)
return -EINVAL;
if (dev->msi_domain->bus_token != DOMAIN_BUS_PLATFORM_MSI) {
@@ -238,7 +246,7 @@ int platform_msi_domain_alloc_irqs(struct device *dev, unsigned int nvec,
return 0;
out_free_desc:
- platform_msi_free_descs(dev);
+ platform_msi_free_descs(dev, 0, nvec);
out_free_id:
ida_simple_remove(&platform_msi_devid_ida, priv_data->devid);
out_free_data:
@@ -266,5 +274,5 @@ void platform_msi_domain_free_irqs(struct device *dev)
}
msi_domain_free_irqs(dev->msi_domain, dev);
- platform_msi_free_descs(dev);
+ platform_msi_free_descs(dev, 0, MAX_DEV_MSIS);
}
--
2.1.4
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH RFC 2/7] platform-msi: Factor out allocation/free of private data
2015-10-15 15:39 [PATCH RFC 0/7] Adding core support for wire-MSI bridges Marc Zyngier
2015-10-15 15:39 ` [PATCH RFC 1/7] platform-msi: Allow MSIs to be allocated in chunks Marc Zyngier
@ 2015-10-15 15:39 ` Marc Zyngier
2015-10-16 5:46 ` Jiang Liu
2015-10-15 15:39 ` [PATCH RFC 3/7] irqdomain: Make irq_domain_alloc_irqs_recursive available Marc Zyngier
` (6 subsequent siblings)
8 siblings, 1 reply; 30+ messages in thread
From: Marc Zyngier @ 2015-10-15 15:39 UTC (permalink / raw)
To: Thomas Gleixner, Jiang Liu, Jason Cooper
Cc: Ma Jun, linux-arm-kernel, linux-pci, linux-kernel
As we're going to have multiple paths to allocate/free the
platform-msi private data, factor this out into separate
utility functions.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
drivers/base/platform-msi.c | 84 ++++++++++++++++++++++++++-------------------
1 file changed, 48 insertions(+), 36 deletions(-)
diff --git a/drivers/base/platform-msi.c b/drivers/base/platform-msi.c
index 6148c78..92666cd 100644
--- a/drivers/base/platform-msi.c
+++ b/drivers/base/platform-msi.c
@@ -189,21 +189,11 @@ struct irq_domain *platform_msi_create_irq_domain(struct fwnode_handle *fwnode,
return domain;
}
-/**
- * platform_msi_domain_alloc_irqs - Allocate MSI interrupts for @dev
- * @dev: The device for which to allocate interrupts
- * @nvec: The number of interrupts to allocate
- * @write_msi_msg: Callback to write an interrupt message for @dev
- *
- * Returns:
- * Zero for success, or an error code in case of failure
- */
-int platform_msi_domain_alloc_irqs(struct device *dev, unsigned int nvec,
- irq_write_msi_msg_t write_msi_msg)
+static int platform_msi_alloc_priv_data(struct device *dev, unsigned int nvec,
+ irq_write_msi_msg_t write_msi_msg,
+ struct platform_msi_priv_data **data)
{
- struct platform_msi_priv_data *priv_data;
- int err;
-
+ struct platform_msi_priv_data *datap;
/*
* Limit the number of interrupts to 256 per device. Should we
* need to bump this up, DEV_ID_SHIFT should be adjusted
@@ -222,22 +212,51 @@ int platform_msi_domain_alloc_irqs(struct device *dev, unsigned int nvec,
if (!list_empty(dev_to_msi_list(dev)))
return -EBUSY;
- priv_data = kzalloc(sizeof(*priv_data), GFP_KERNEL);
- if (!priv_data)
+ datap = *data = kzalloc(sizeof(**data), GFP_KERNEL);
+ if (!datap)
return -ENOMEM;
- priv_data->devid = ida_simple_get(&platform_msi_devid_ida,
- 0, 1 << DEV_ID_SHIFT, GFP_KERNEL);
- if (priv_data->devid < 0) {
- err = priv_data->devid;
- goto out_free_data;
+ datap->devid = ida_simple_get(&platform_msi_devid_ida,
+ 0, 1 << DEV_ID_SHIFT, GFP_KERNEL);
+ if (datap->devid < 0) {
+ int err = datap->devid;
+ kfree(*data);
+ return err;
}
- priv_data->write_msg = write_msi_msg;
+ datap->write_msg = write_msi_msg;
+
+ return 0;
+}
+
+static void platform_msi_free_priv_data(struct platform_msi_priv_data *data)
+{
+ ida_simple_remove(&platform_msi_devid_ida, data->devid);
+ kfree(data);
+}
+
+/**
+ * platform_msi_domain_alloc_irqs - Allocate MSI interrupts for @dev
+ * @dev: The device for which to allocate interrupts
+ * @nvec: The number of interrupts to allocate
+ * @write_msi_msg: Callback to write an interrupt message for @dev
+ *
+ * Returns:
+ * Zero for success, or an error code in case of failure
+ */
+int platform_msi_domain_alloc_irqs(struct device *dev, unsigned int nvec,
+ irq_write_msi_msg_t write_msi_msg)
+{
+ struct platform_msi_priv_data *priv_data;
+ int err;
+
+ err = platform_msi_alloc_priv_data(dev, nvec, write_msi_msg, &priv_data);
+ if (err)
+ return err;
err = platform_msi_alloc_descs(dev, nvec, priv_data);
if (err)
- goto out_free_id;
+ goto out_free_priv_data;
err = msi_domain_alloc_irqs(dev->msi_domain, dev, nvec);
if (err)
@@ -247,10 +266,8 @@ int platform_msi_domain_alloc_irqs(struct device *dev, unsigned int nvec,
out_free_desc:
platform_msi_free_descs(dev, 0, nvec);
-out_free_id:
- ida_simple_remove(&platform_msi_devid_ida, priv_data->devid);
-out_free_data:
- kfree(priv_data);
+out_free_priv_data:
+ platform_msi_free_priv_data(priv_data);
return err;
}
@@ -261,16 +278,11 @@ out_free_data:
*/
void platform_msi_domain_free_irqs(struct device *dev)
{
- struct msi_desc *desc;
-
- desc = first_msi_entry(dev);
- if (desc) {
- struct platform_msi_priv_data *data;
-
- data = desc->platform.msi_priv_data;
+ if (!list_empty(dev_to_msi_list(dev))) {
+ struct msi_desc *desc;
- ida_simple_remove(&platform_msi_devid_ida, data->devid);
- kfree(data);
+ desc = first_msi_entry(dev);
+ platform_msi_free_priv_data(desc->platform.msi_priv_data);
}
msi_domain_free_irqs(dev->msi_domain, dev);
--
2.1.4
^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: [PATCH RFC 2/7] platform-msi: Factor out allocation/free of private data
2015-10-15 15:39 ` [PATCH RFC 2/7] platform-msi: Factor out allocation/free of private data Marc Zyngier
@ 2015-10-16 5:46 ` Jiang Liu
2015-10-16 8:50 ` Marc Zyngier
0 siblings, 1 reply; 30+ messages in thread
From: Jiang Liu @ 2015-10-16 5:46 UTC (permalink / raw)
To: Marc Zyngier, Thomas Gleixner, Jason Cooper
Cc: Ma Jun, linux-arm-kernel, linux-pci, linux-kernel
On 2015/10/15 23:39, Marc Zyngier wrote:
> As we're going to have multiple paths to allocate/free the
> platform-msi private data, factor this out into separate
> utility functions.
>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
> drivers/base/platform-msi.c | 84 ++++++++++++++++++++++++++-------------------
> 1 file changed, 48 insertions(+), 36 deletions(-)
>
> diff --git a/drivers/base/platform-msi.c b/drivers/base/platform-msi.c
> index 6148c78..92666cd 100644
> --- a/drivers/base/platform-msi.c
> +++ b/drivers/base/platform-msi.c
> @@ -189,21 +189,11 @@ struct irq_domain *platform_msi_create_irq_domain(struct fwnode_handle *fwnode,
> return domain;
> }
>
> -/**
> - * platform_msi_domain_alloc_irqs - Allocate MSI interrupts for @dev
> - * @dev: The device for which to allocate interrupts
> - * @nvec: The number of interrupts to allocate
> - * @write_msi_msg: Callback to write an interrupt message for @dev
> - *
> - * Returns:
> - * Zero for success, or an error code in case of failure
> - */
> -int platform_msi_domain_alloc_irqs(struct device *dev, unsigned int nvec,
> - irq_write_msi_msg_t write_msi_msg)
> +static int platform_msi_alloc_priv_data(struct device *dev, unsigned int nvec,
> + irq_write_msi_msg_t write_msi_msg,
> + struct platform_msi_priv_data **data)
How about making platform_msi_alloc_priv_data() return a pointer
instead of an int, that may simplify the code a bit.
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH RFC 2/7] platform-msi: Factor out allocation/free of private data
2015-10-16 5:46 ` Jiang Liu
@ 2015-10-16 8:50 ` Marc Zyngier
0 siblings, 0 replies; 30+ messages in thread
From: Marc Zyngier @ 2015-10-16 8:50 UTC (permalink / raw)
To: Jiang Liu, Thomas Gleixner, Jason Cooper
Cc: Ma Jun, linux-arm-kernel, linux-pci, linux-kernel
On 16/10/15 06:46, Jiang Liu wrote:
> On 2015/10/15 23:39, Marc Zyngier wrote:
>> As we're going to have multiple paths to allocate/free the
>> platform-msi private data, factor this out into separate
>> utility functions.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>> drivers/base/platform-msi.c | 84 ++++++++++++++++++++++++++-------------------
>> 1 file changed, 48 insertions(+), 36 deletions(-)
>>
>> diff --git a/drivers/base/platform-msi.c b/drivers/base/platform-msi.c
>> index 6148c78..92666cd 100644
>> --- a/drivers/base/platform-msi.c
>> +++ b/drivers/base/platform-msi.c
>> @@ -189,21 +189,11 @@ struct irq_domain *platform_msi_create_irq_domain(struct fwnode_handle *fwnode,
>> return domain;
>> }
>>
>> -/**
>> - * platform_msi_domain_alloc_irqs - Allocate MSI interrupts for @dev
>> - * @dev: The device for which to allocate interrupts
>> - * @nvec: The number of interrupts to allocate
>> - * @write_msi_msg: Callback to write an interrupt message for @dev
>> - *
>> - * Returns:
>> - * Zero for success, or an error code in case of failure
>> - */
>> -int platform_msi_domain_alloc_irqs(struct device *dev, unsigned int nvec,
>> - irq_write_msi_msg_t write_msi_msg)
>> +static int platform_msi_alloc_priv_data(struct device *dev, unsigned int nvec,
>> + irq_write_msi_msg_t write_msi_msg,
>> + struct platform_msi_priv_data **data)
> How about making platform_msi_alloc_priv_data() return a pointer
> instead of an int, that may simplify the code a bit.
>
That's a good point. I could encode the error code in the return pointer
(PTR_ERR).
Thanks,
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH RFC 3/7] irqdomain: Make irq_domain_alloc_irqs_recursive available
2015-10-15 15:39 [PATCH RFC 0/7] Adding core support for wire-MSI bridges Marc Zyngier
2015-10-15 15:39 ` [PATCH RFC 1/7] platform-msi: Allow MSIs to be allocated in chunks Marc Zyngier
2015-10-15 15:39 ` [PATCH RFC 2/7] platform-msi: Factor out allocation/free of private data Marc Zyngier
@ 2015-10-15 15:39 ` Marc Zyngier
2015-10-15 15:39 ` [PATCH RFC 4/7] genirq/msi: Make the .prepare callback reusable Marc Zyngier
` (5 subsequent siblings)
8 siblings, 0 replies; 30+ messages in thread
From: Marc Zyngier @ 2015-10-15 15:39 UTC (permalink / raw)
To: Thomas Gleixner, Jiang Liu, Jason Cooper
Cc: Ma Jun, linux-arm-kernel, linux-pci, linux-kernel
We are soon going to need the MSI layer to call into the domain
allocators. Instead of open coding this, make the standard
irq_domain_alloc_irqs_recursive function available to the MSI
layer.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
include/linux/irqdomain.h | 3 +++
kernel/irq/irqdomain.c | 6 +++---
2 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index d5e5c5b..cf96c6a 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -367,6 +367,9 @@ static inline int irq_domain_alloc_irqs(struct irq_domain *domain,
return __irq_domain_alloc_irqs(domain, -1, nr_irqs, node, arg, false);
}
+extern int irq_domain_alloc_irqs_recursive(struct irq_domain *domain,
+ unsigned int irq_base,
+ unsigned int nr_irqs, void *arg);
extern int irq_domain_set_hwirq_and_chip(struct irq_domain *domain,
unsigned int virq,
irq_hw_number_t hwirq,
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 22aa961..1c9973e 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -1125,9 +1125,9 @@ static void irq_domain_free_irqs_recursive(struct irq_domain *domain,
}
}
-static int irq_domain_alloc_irqs_recursive(struct irq_domain *domain,
- unsigned int irq_base,
- unsigned int nr_irqs, void *arg)
+int irq_domain_alloc_irqs_recursive(struct irq_domain *domain,
+ unsigned int irq_base,
+ unsigned int nr_irqs, void *arg)
{
int ret = 0;
struct irq_domain *parent = domain->parent;
--
2.1.4
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH RFC 4/7] genirq/msi: Make the .prepare callback reusable
2015-10-15 15:39 [PATCH RFC 0/7] Adding core support for wire-MSI bridges Marc Zyngier
` (2 preceding siblings ...)
2015-10-15 15:39 ` [PATCH RFC 3/7] irqdomain: Make irq_domain_alloc_irqs_recursive available Marc Zyngier
@ 2015-10-15 15:39 ` Marc Zyngier
2015-10-15 17:24 ` Gabriele Paoloni
2015-10-16 5:45 ` Jiang Liu
2015-10-15 15:39 ` [PATCH RFC 5/7] genirq/msi: Add msi_domain_populate_irqs Marc Zyngier
` (4 subsequent siblings)
8 siblings, 2 replies; 30+ messages in thread
From: Marc Zyngier @ 2015-10-15 15:39 UTC (permalink / raw)
To: Thomas Gleixner, Jiang Liu, Jason Cooper
Cc: Ma Jun, linux-arm-kernel, linux-pci, linux-kernel
The .prepare callbacks are so far only called from msi_domain_alloc_irqs.
In order to reuse that code, split that code and create a
msi_domain_prepare_irqs function that the existing code can call into.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
include/linux/msi.h | 4 ++++
kernel/irq/msi.c | 20 +++++++++++++++++---
2 files changed, 21 insertions(+), 3 deletions(-)
diff --git a/include/linux/msi.h b/include/linux/msi.h
index 32a24b9..5bb36a9 100644
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -277,6 +277,10 @@ struct irq_domain *platform_msi_create_irq_domain(struct fwnode_handle *fwnode,
int platform_msi_domain_alloc_irqs(struct device *dev, unsigned int nvec,
irq_write_msi_msg_t write_msi_msg);
void platform_msi_domain_free_irqs(struct device *dev);
+
+/* When an MSI domain is used as an intermediate domain */
+int msi_domain_prepare_irqs(struct irq_domain *domain, struct device *dev,
+ int nvec, msi_alloc_info_t *args);
#endif /* CONFIG_GENERIC_MSI_IRQ_DOMAIN */
#ifdef CONFIG_PCI_MSI_IRQ_DOMAIN
diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c
index 95354bb..8e6e112 100644
--- a/kernel/irq/msi.c
+++ b/kernel/irq/msi.c
@@ -256,6 +256,22 @@ struct irq_domain *msi_create_irq_domain(struct fwnode_handle *fwnode,
&msi_domain_ops, info);
}
+int msi_domain_prepare_irqs(struct irq_domain *domain, struct device *dev,
+ int nvec, msi_alloc_info_t *arg)
+{
+ struct msi_domain_info *info = domain->host_data;
+ struct msi_domain_ops *ops = info->ops;
+ int ret;
+
+ ret = ops->msi_check(domain, info, dev);
+ if (ret == 0)
+ ret = ops->msi_prepare(domain, dev, nvec, arg);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
/**
* msi_domain_alloc_irqs - Allocate interrupts from a MSI interrupt domain
* @domain: The domain to allocate from
@@ -274,9 +290,7 @@ int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,
struct msi_desc *desc;
int i, ret, virq = -1;
- ret = ops->msi_check(domain, info, dev);
- if (ret == 0)
- ret = ops->msi_prepare(domain, dev, nvec, &arg);
+ ret = msi_domain_prepare_irqs(domain, dev, nvec, &arg);
if (ret)
return ret;
--
2.1.4
^ permalink raw reply related [flat|nested] 30+ messages in thread
* RE: [PATCH RFC 4/7] genirq/msi: Make the .prepare callback reusable
2015-10-15 15:39 ` [PATCH RFC 4/7] genirq/msi: Make the .prepare callback reusable Marc Zyngier
@ 2015-10-15 17:24 ` Gabriele Paoloni
2015-10-15 17:39 ` Marc Zyngier
2015-10-16 5:45 ` Jiang Liu
1 sibling, 1 reply; 30+ messages in thread
From: Gabriele Paoloni @ 2015-10-15 17:24 UTC (permalink / raw)
To: Marc Zyngier, Thomas Gleixner, Jiang Liu, Jason Cooper
Cc: majun (F), linux-arm-kernel@lists.infradead.org,
linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org
SGkgTWFyYw0KDQpJdCBsb29rcyBsaWtlIHRoaXMgcGF0Y2ggZmFpbHMgdG8gYXBwbHkgdG8gNC4z
LXJjNS4uLi4NCg0KR2FiDQoNCj4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gRnJvbTog
bGludXgtcGNpLW93bmVyQHZnZXIua2VybmVsLm9yZyBbbWFpbHRvOmxpbnV4LXBjaS0NCj4gb3du
ZXJAdmdlci5rZXJuZWwub3JnXSBPbiBCZWhhbGYgT2YgTWFyYyBaeW5naWVyDQo+IFNlbnQ6IFRo
dXJzZGF5LCBPY3RvYmVyIDE1LCAyMDE1IDQ6MzkgUE0NCj4gVG86IFRob21hcyBHbGVpeG5lcjsg
SmlhbmcgTGl1OyBKYXNvbiBDb29wZXINCj4gQ2M6IG1hanVuIChGKTsgbGludXgtYXJtLWtlcm5l
bEBsaXN0cy5pbmZyYWRlYWQub3JnOyBsaW51eC0NCj4gcGNpQHZnZXIua2VybmVsLm9yZzsgbGlu
dXgta2VybmVsQHZnZXIua2VybmVsLm9yZw0KPiBTdWJqZWN0OiBbUEFUQ0ggUkZDIDQvN10gZ2Vu
aXJxL21zaTogTWFrZSB0aGUgLnByZXBhcmUgY2FsbGJhY2sNCj4gcmV1c2FibGUNCj4gDQo+IFRo
ZSAucHJlcGFyZSBjYWxsYmFja3MgYXJlIHNvIGZhciBvbmx5IGNhbGxlZCBmcm9tDQo+IG1zaV9k
b21haW5fYWxsb2NfaXJxcy4NCj4gSW4gb3JkZXIgdG8gcmV1c2UgdGhhdCBjb2RlLCBzcGxpdCB0
aGF0IGNvZGUgYW5kIGNyZWF0ZSBhDQo+IG1zaV9kb21haW5fcHJlcGFyZV9pcnFzIGZ1bmN0aW9u
IHRoYXQgdGhlIGV4aXN0aW5nIGNvZGUgY2FuIGNhbGwgaW50by4NCj4gDQo+IFNpZ25lZC1vZmYt
Ynk6IE1hcmMgWnluZ2llciA8bWFyYy56eW5naWVyQGFybS5jb20+DQo+IC0tLQ0KPiAgaW5jbHVk
ZS9saW51eC9tc2kuaCB8ICA0ICsrKysNCj4gIGtlcm5lbC9pcnEvbXNpLmMgICAgfCAyMCArKysr
KysrKysrKysrKysrKy0tLQ0KPiAgMiBmaWxlcyBjaGFuZ2VkLCAyMSBpbnNlcnRpb25zKCspLCAz
IGRlbGV0aW9ucygtKQ0KPiANCj4gZGlmZiAtLWdpdCBhL2luY2x1ZGUvbGludXgvbXNpLmggYi9p
bmNsdWRlL2xpbnV4L21zaS5oDQo+IGluZGV4IDMyYTI0YjkuLjViYjM2YTkgMTAwNjQ0DQo+IC0t
LSBhL2luY2x1ZGUvbGludXgvbXNpLmgNCj4gKysrIGIvaW5jbHVkZS9saW51eC9tc2kuaA0KPiBA
QCAtMjc3LDYgKzI3NywxMCBAQCBzdHJ1Y3QgaXJxX2RvbWFpbg0KPiAqcGxhdGZvcm1fbXNpX2Ny
ZWF0ZV9pcnFfZG9tYWluKHN0cnVjdCBmd25vZGVfaGFuZGxlICpmd25vZGUsDQo+ICBpbnQgcGxh
dGZvcm1fbXNpX2RvbWFpbl9hbGxvY19pcnFzKHN0cnVjdCBkZXZpY2UgKmRldiwgdW5zaWduZWQg
aW50DQo+IG52ZWMsDQo+ICAJCQkJICAgaXJxX3dyaXRlX21zaV9tc2dfdCB3cml0ZV9tc2lfbXNn
KTsNCj4gIHZvaWQgcGxhdGZvcm1fbXNpX2RvbWFpbl9mcmVlX2lycXMoc3RydWN0IGRldmljZSAq
ZGV2KTsNCj4gKw0KPiArLyogV2hlbiBhbiBNU0kgZG9tYWluIGlzIHVzZWQgYXMgYW4gaW50ZXJt
ZWRpYXRlIGRvbWFpbiAqLw0KPiAraW50IG1zaV9kb21haW5fcHJlcGFyZV9pcnFzKHN0cnVjdCBp
cnFfZG9tYWluICpkb21haW4sIHN0cnVjdCBkZXZpY2UNCj4gKmRldiwNCj4gKwkJCSAgICBpbnQg
bnZlYywgbXNpX2FsbG9jX2luZm9fdCAqYXJncyk7DQo+ICAjZW5kaWYgLyogQ09ORklHX0dFTkVS
SUNfTVNJX0lSUV9ET01BSU4gKi8NCj4gDQo+ICAjaWZkZWYgQ09ORklHX1BDSV9NU0lfSVJRX0RP
TUFJTg0KPiBkaWZmIC0tZ2l0IGEva2VybmVsL2lycS9tc2kuYyBiL2tlcm5lbC9pcnEvbXNpLmMN
Cj4gaW5kZXggOTUzNTRiYi4uOGU2ZTExMiAxMDA2NDQNCj4gLS0tIGEva2VybmVsL2lycS9tc2ku
Yw0KPiArKysgYi9rZXJuZWwvaXJxL21zaS5jDQo+IEBAIC0yNTYsNiArMjU2LDIyIEBAIHN0cnVj
dCBpcnFfZG9tYWluICptc2lfY3JlYXRlX2lycV9kb21haW4oc3RydWN0DQo+IGZ3bm9kZV9oYW5k
bGUgKmZ3bm9kZSwNCj4gIAkJCQkJICAgJm1zaV9kb21haW5fb3BzLCBpbmZvKTsNCj4gIH0NCj4g
DQo+ICtpbnQgbXNpX2RvbWFpbl9wcmVwYXJlX2lycXMoc3RydWN0IGlycV9kb21haW4gKmRvbWFp
biwgc3RydWN0IGRldmljZQ0KPiAqZGV2LA0KPiArCQkJICAgIGludCBudmVjLCBtc2lfYWxsb2Nf
aW5mb190ICphcmcpDQo+ICt7DQo+ICsJc3RydWN0IG1zaV9kb21haW5faW5mbyAqaW5mbyA9IGRv
bWFpbi0+aG9zdF9kYXRhOw0KPiArCXN0cnVjdCBtc2lfZG9tYWluX29wcyAqb3BzID0gaW5mby0+
b3BzOw0KPiArCWludCByZXQ7DQo+ICsNCj4gKwlyZXQgPSBvcHMtPm1zaV9jaGVjayhkb21haW4s
IGluZm8sIGRldik7DQo+ICsJaWYgKHJldCA9PSAwKQ0KPiArCQlyZXQgPSBvcHMtPm1zaV9wcmVw
YXJlKGRvbWFpbiwgZGV2LCBudmVjLCBhcmcpOw0KPiArCWlmIChyZXQpDQo+ICsJCXJldHVybiBy
ZXQ7DQo+ICsNCj4gKwlyZXR1cm4gMDsNCj4gK30NCj4gKw0KPiAgLyoqDQo+ICAgKiBtc2lfZG9t
YWluX2FsbG9jX2lycXMgLSBBbGxvY2F0ZSBpbnRlcnJ1cHRzIGZyb20gYSBNU0kgaW50ZXJydXB0
DQo+IGRvbWFpbg0KPiAgICogQGRvbWFpbjoJVGhlIGRvbWFpbiB0byBhbGxvY2F0ZSBmcm9tDQo+
IEBAIC0yNzQsOSArMjkwLDcgQEAgaW50IG1zaV9kb21haW5fYWxsb2NfaXJxcyhzdHJ1Y3QgaXJx
X2RvbWFpbiAqZG9tYWluLA0KPiBzdHJ1Y3QgZGV2aWNlICpkZXYsDQo+ICAJc3RydWN0IG1zaV9k
ZXNjICpkZXNjOw0KPiAgCWludCBpLCByZXQsIHZpcnEgPSAtMTsNCj4gDQo+IC0JcmV0ID0gb3Bz
LT5tc2lfY2hlY2soZG9tYWluLCBpbmZvLCBkZXYpOw0KPiAtCWlmIChyZXQgPT0gMCkNCj4gLQkJ
cmV0ID0gb3BzLT5tc2lfcHJlcGFyZShkb21haW4sIGRldiwgbnZlYywgJmFyZyk7DQo+ICsJcmV0
ID0gbXNpX2RvbWFpbl9wcmVwYXJlX2lycXMoZG9tYWluLCBkZXYsIG52ZWMsICZhcmcpOw0KPiAg
CWlmIChyZXQpDQo+ICAJCXJldHVybiByZXQ7DQo+IA0KPiAtLQ0KPiAyLjEuNA0KPiANCj4gLS0N
Cj4gVG8gdW5zdWJzY3JpYmUgZnJvbSB0aGlzIGxpc3Q6IHNlbmQgdGhlIGxpbmUgInVuc3Vic2Ny
aWJlIGxpbnV4LXBjaSIgaW4NCj4gdGhlIGJvZHkgb2YgYSBtZXNzYWdlIHRvIG1ham9yZG9tb0B2
Z2VyLmtlcm5lbC5vcmcNCj4gTW9yZSBtYWpvcmRvbW8gaW5mbyBhdCAgaHR0cDovL3ZnZXIua2Vy
bmVsLm9yZy9tYWpvcmRvbW8taW5mby5odG1sDQo=
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH RFC 4/7] genirq/msi: Make the .prepare callback reusable
2015-10-15 17:24 ` Gabriele Paoloni
@ 2015-10-15 17:39 ` Marc Zyngier
2015-10-16 13:07 ` Gabriele Paoloni
0 siblings, 1 reply; 30+ messages in thread
From: Marc Zyngier @ 2015-10-15 17:39 UTC (permalink / raw)
To: Gabriele Paoloni, Thomas Gleixner, Jiang Liu, Jason Cooper
Cc: majun (F), linux-arm-kernel@lists.infradead.org,
linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org
On 15/10/15 18:24, Gabriele Paoloni wrote:
> Hi Marc
>
> It looks like this patch fails to apply to 4.3-rc5....
Which is by design. Try tip/irq/core.
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply [flat|nested] 30+ messages in thread
* RE: [PATCH RFC 4/7] genirq/msi: Make the .prepare callback reusable
2015-10-15 17:39 ` Marc Zyngier
@ 2015-10-16 13:07 ` Gabriele Paoloni
0 siblings, 0 replies; 30+ messages in thread
From: Gabriele Paoloni @ 2015-10-16 13:07 UTC (permalink / raw)
To: Marc Zyngier, Thomas Gleixner, Jiang Liu, Jason Cooper
Cc: majun (F), linux-arm-kernel@lists.infradead.org,
linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org
PiAtLS0tLU9yaWdpbmFsIE1lc3NhZ2UtLS0tLQ0KPiBGcm9tOiBsaW51eC1rZXJuZWwtb3duZXJA
dmdlci5rZXJuZWwub3JnIFttYWlsdG86bGludXgta2VybmVsLQ0KPiBvd25lckB2Z2VyLmtlcm5l
bC5vcmddIE9uIEJlaGFsZiBPZiBNYXJjIFp5bmdpZXINCj4gU2VudDogVGh1cnNkYXksIE9jdG9i
ZXIgMTUsIDIwMTUgNjozOSBQTQ0KPiBUbzogR2FicmllbGUgUGFvbG9uaTsgVGhvbWFzIEdsZWl4
bmVyOyBKaWFuZyBMaXU7IEphc29uIENvb3Blcg0KPiBDYzogbWFqdW4gKEYpOyBsaW51eC1hcm0t
a2VybmVsQGxpc3RzLmluZnJhZGVhZC5vcmc7IGxpbnV4LQ0KPiBwY2lAdmdlci5rZXJuZWwub3Jn
OyBsaW51eC1rZXJuZWxAdmdlci5rZXJuZWwub3JnDQo+IFN1YmplY3Q6IFJlOiBbUEFUQ0ggUkZD
IDQvN10gZ2VuaXJxL21zaTogTWFrZSB0aGUgLnByZXBhcmUgY2FsbGJhY2sNCj4gcmV1c2FibGUN
Cj4gDQo+IE9uIDE1LzEwLzE1IDE4OjI0LCBHYWJyaWVsZSBQYW9sb25pIHdyb3RlOg0KPiA+IEhp
IE1hcmMNCj4gPg0KPiA+IEl0IGxvb2tzIGxpa2UgdGhpcyBwYXRjaCBmYWlscyB0byBhcHBseSB0
byA0LjMtcmM1Li4uLg0KPiANCj4gV2hpY2ggaXMgYnkgZGVzaWduLiBUcnkgdGlwL2lycS9jb3Jl
Lg0KDQpPb3BzIHNvcnJ5LCBnb3QgaXQhDQoNClRoYW5rcywgYXBwbGllcyBvayB0byB0aXAvaXJx
L2NvcmUNCg0KR2FiDQoNCg0KPiANCj4gCU0uDQo+IC0tDQo+IEphenogaXMgbm90IGRlYWQuIEl0
IGp1c3Qgc21lbGxzIGZ1bm55Li4uDQo+IC0tDQo+IFRvIHVuc3Vic2NyaWJlIGZyb20gdGhpcyBs
aXN0OiBzZW5kIHRoZSBsaW5lICJ1bnN1YnNjcmliZSBsaW51eC1rZXJuZWwiDQo+IGluDQo+IHRo
ZSBib2R5IG9mIGEgbWVzc2FnZSB0byBtYWpvcmRvbW9Admdlci5rZXJuZWwub3JnDQo+IE1vcmUg
bWFqb3Jkb21vIGluZm8gYXQgIGh0dHA6Ly92Z2VyLmtlcm5lbC5vcmcvbWFqb3Jkb21vLWluZm8u
aHRtbA0KPiBQbGVhc2UgcmVhZCB0aGUgRkFRIGF0ICBodHRwOi8vd3d3LnR1eC5vcmcvbGttbC8N
Cg==
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH RFC 4/7] genirq/msi: Make the .prepare callback reusable
2015-10-15 15:39 ` [PATCH RFC 4/7] genirq/msi: Make the .prepare callback reusable Marc Zyngier
2015-10-15 17:24 ` Gabriele Paoloni
@ 2015-10-16 5:45 ` Jiang Liu
2015-10-16 8:48 ` Marc Zyngier
1 sibling, 1 reply; 30+ messages in thread
From: Jiang Liu @ 2015-10-16 5:45 UTC (permalink / raw)
To: Marc Zyngier, Thomas Gleixner, Jason Cooper
Cc: Ma Jun, linux-arm-kernel, linux-pci, linux-kernel
On 2015/10/15 23:39, Marc Zyngier wrote:
<snit>
> +int msi_domain_prepare_irqs(struct irq_domain *domain, struct device *dev,
> + int nvec, msi_alloc_info_t *arg)
> +{
> + struct msi_domain_info *info = domain->host_data;
> + struct msi_domain_ops *ops = info->ops;
> + int ret;
> +
> + ret = ops->msi_check(domain, info, dev);
> + if (ret == 0)
> + ret = ops->msi_prepare(domain, dev, nvec, arg);
> + if (ret)
> + return ret;
> +
> + return 0;
Seems a simple "return ret" is enough:)
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH RFC 4/7] genirq/msi: Make the .prepare callback reusable
2015-10-16 5:45 ` Jiang Liu
@ 2015-10-16 8:48 ` Marc Zyngier
0 siblings, 0 replies; 30+ messages in thread
From: Marc Zyngier @ 2015-10-16 8:48 UTC (permalink / raw)
To: Jiang Liu, Thomas Gleixner, Jason Cooper
Cc: Ma Jun, linux-arm-kernel, linux-pci, linux-kernel
On 16/10/15 06:45, Jiang Liu wrote:
> On 2015/10/15 23:39, Marc Zyngier wrote:
> <snit>
>> +int msi_domain_prepare_irqs(struct irq_domain *domain, struct device *dev,
>> + int nvec, msi_alloc_info_t *arg)
>> +{
>> + struct msi_domain_info *info = domain->host_data;
>> + struct msi_domain_ops *ops = info->ops;
>> + int ret;
>> +
>> + ret = ops->msi_check(domain, info, dev);
>> + if (ret == 0)
>> + ret = ops->msi_prepare(domain, dev, nvec, arg);
>> + if (ret)
>> + return ret;
>> +
>> + return 0;
> Seems a simple "return ret" is enough:)
Ah! yes! ;-)
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH RFC 5/7] genirq/msi: Add msi_domain_populate_irqs
2015-10-15 15:39 [PATCH RFC 0/7] Adding core support for wire-MSI bridges Marc Zyngier
` (3 preceding siblings ...)
2015-10-15 15:39 ` [PATCH RFC 4/7] genirq/msi: Make the .prepare callback reusable Marc Zyngier
@ 2015-10-15 15:39 ` Marc Zyngier
2015-10-15 15:39 ` [PATCH RFC 6/7] platform-msi: Allow creation of a MSI-based stacked irq domain Marc Zyngier
` (3 subsequent siblings)
8 siblings, 0 replies; 30+ messages in thread
From: Marc Zyngier @ 2015-10-15 15:39 UTC (permalink / raw)
To: Thomas Gleixner, Jiang Liu, Jason Cooper
Cc: Ma Jun, linux-arm-kernel, linux-pci, linux-kernel
To be able to allocate interrupts from the MSI layer down,
add a new msi_domain_populate_irqs entry point.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
include/linux/msi.h | 2 ++
kernel/irq/msi.c | 27 +++++++++++++++++++++++++++
2 files changed, 29 insertions(+)
diff --git a/include/linux/msi.h b/include/linux/msi.h
index 5bb36a9..e35558c 100644
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -281,6 +281,8 @@ void platform_msi_domain_free_irqs(struct device *dev);
/* When an MSI domain is used as an intermediate domain */
int msi_domain_prepare_irqs(struct irq_domain *domain, struct device *dev,
int nvec, msi_alloc_info_t *args);
+int msi_domain_populate_irqs(struct irq_domain *domain, struct device *dev,
+ int virq, int nvec, msi_alloc_info_t *args);
#endif /* CONFIG_GENERIC_MSI_IRQ_DOMAIN */
#ifdef CONFIG_PCI_MSI_IRQ_DOMAIN
diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c
index 8e6e112..53118e9 100644
--- a/kernel/irq/msi.c
+++ b/kernel/irq/msi.c
@@ -272,6 +272,33 @@ int msi_domain_prepare_irqs(struct irq_domain *domain, struct device *dev,
return 0;
}
+int msi_domain_populate_irqs(struct irq_domain *domain, struct device *dev,
+ int virq, int nvec, msi_alloc_info_t *arg)
+{
+ struct msi_domain_info *info = domain->host_data;
+ struct msi_domain_ops *ops = info->ops;
+ struct msi_desc *desc;
+
+ for_each_msi_entry(desc, dev) {
+ int i, ret;
+
+ if (!(desc->irq >= virq && desc->irq < (virq + nvec)))
+ continue;
+
+ ops->set_desc(arg, desc);
+ /* Assumes the domain mutex is held! */
+ ret = irq_domain_alloc_irqs_recursive(domain, virq, nvec, arg);
+ /* FIXME: Error handling */
+ if (ret)
+ return ret;
+
+ for (i = 0; i < desc->nvec_used; i++)
+ irq_set_msi_desc_off(virq, i, desc);
+ }
+
+ return 0;
+}
+
/**
* msi_domain_alloc_irqs - Allocate interrupts from a MSI interrupt domain
* @domain: The domain to allocate from
--
2.1.4
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH RFC 6/7] platform-msi: Allow creation of a MSI-based stacked irq domain
2015-10-15 15:39 [PATCH RFC 0/7] Adding core support for wire-MSI bridges Marc Zyngier
` (4 preceding siblings ...)
2015-10-15 15:39 ` [PATCH RFC 5/7] genirq/msi: Add msi_domain_populate_irqs Marc Zyngier
@ 2015-10-15 15:39 ` Marc Zyngier
2015-10-15 15:39 ` [PATCH RFC 7/7] irqchip: [Example] dummy wired interrupt/MSI bridge driver Marc Zyngier
` (2 subsequent siblings)
8 siblings, 0 replies; 30+ messages in thread
From: Marc Zyngier @ 2015-10-15 15:39 UTC (permalink / raw)
To: Thomas Gleixner, Jiang Liu, Jason Cooper
Cc: Ma Jun, linux-arm-kernel, linux-pci, linux-kernel
We almost have all the needed bits to be able to create a irq domain
on top of a MSI domain.
For this, we enable a few things:
- the virq is stored in the msi_desc
- device, msi_alloc_info and domain-specific data
are stored in the platform_pric_data structure
- we introduce a new API for platform-msi:
/* Create a MSI-based domain */
struct irq_domain *
platform_msi_create_device_domain(struct device *dev,
unsigned int nvec,
irq_write_msi_msg_t write_msi_msg,
const struct irq_domain_ops *ops,
void *host_data);
/* Allocate MSIs in an MSI domain */
int platform_msi_domain_alloc(struct irq_domain *domain, unsigned int virq,
unsigned int nr_irqs);
/* Obtain the host data passed to platform_msi_create_device_domain */
void *platform_msi_get_host_data(struct irq_domain *domain);
This now allows a wired irq to MSI bridge to be created.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
drivers/base/platform-msi.c | 71 +++++++++++++++++++++++++++++++++++++++++++--
include/linux/msi.h | 10 +++++++
2 files changed, 79 insertions(+), 2 deletions(-)
diff --git a/drivers/base/platform-msi.c b/drivers/base/platform-msi.c
index 92666cd..29e9b63 100644
--- a/drivers/base/platform-msi.c
+++ b/drivers/base/platform-msi.c
@@ -32,6 +32,9 @@
* and the callback to write the MSI message.
*/
struct platform_msi_priv_data {
+ struct device *dev;
+ void *host_data;
+ msi_alloc_info_t arg;
irq_write_msi_msg_t write_msg;
int devid;
};
@@ -124,8 +127,9 @@ static void platform_msi_free_descs(struct device *dev, int base, int nvec)
}
}
-static int platform_msi_alloc_descs(struct device *dev, int nvec,
- struct platform_msi_priv_data *data)
+static int platform_msi_alloc_descs_with_irq(struct device *dev, int virq,
+ int nvec,
+ struct platform_msi_priv_data *data)
{
struct msi_desc *desc;
@@ -145,6 +149,7 @@ static int platform_msi_alloc_descs(struct device *dev, int nvec,
desc->platform.msi_priv_data = data;
desc->platform.msi_index = base + i;
desc->nvec_used = 1;
+ desc->irq = virq ? virq + i : 0;
list_add_tail(&desc->list, dev_to_msi_list(dev));
}
@@ -159,6 +164,13 @@ static int platform_msi_alloc_descs(struct device *dev, int nvec,
return 0;
}
+static int platform_msi_alloc_descs(struct device *dev, int nvec,
+ struct platform_msi_priv_data *data)
+
+{
+ return platform_msi_alloc_descs_with_irq(dev, 0, nvec, data);
+}
+
/**
* platform_msi_create_irq_domain - Create a platform MSI interrupt domain
* @fwnode: Optional fwnode of the interrupt controller
@@ -225,6 +237,7 @@ static int platform_msi_alloc_priv_data(struct device *dev, unsigned int nvec,
}
datap->write_msg = write_msi_msg;
+ datap->dev = dev;
return 0;
}
@@ -288,3 +301,57 @@ void platform_msi_domain_free_irqs(struct device *dev)
msi_domain_free_irqs(dev->msi_domain, dev);
platform_msi_free_descs(dev, 0, MAX_DEV_MSIS);
}
+
+void *platform_msi_get_host_data(struct irq_domain *domain)
+{
+ struct platform_msi_priv_data *data = domain->host_data;
+ return data->host_data;
+}
+
+struct irq_domain *
+platform_msi_create_device_domain(struct device *dev,
+ unsigned int nvec,
+ irq_write_msi_msg_t write_msi_msg,
+ const struct irq_domain_ops *ops,
+ void *host_data)
+{
+ struct platform_msi_priv_data *data;
+ struct irq_domain *domain;
+ int err;
+
+ err = platform_msi_alloc_priv_data(dev, nvec, write_msi_msg, &data);
+ if (err)
+ return NULL;
+
+ data->host_data = host_data;
+ domain = irq_domain_create_hierarchy(dev->msi_domain, 0, nvec,
+ of_node_to_fwnode(dev->of_node),
+ ops, data);
+ if (!domain) {
+ platform_msi_free_priv_data(data);
+ return NULL;
+ }
+
+ /* FIXME: Add better error handling... */
+ err = msi_domain_prepare_irqs(domain->parent, dev, nvec, &data->arg);
+ BUG_ON(err);
+
+ return domain;
+}
+
+int platform_msi_domain_alloc(struct irq_domain *domain, unsigned int virq,
+ unsigned int nr_irqs)
+{
+ struct platform_msi_priv_data *data = domain->host_data;
+ int err;
+
+ err = platform_msi_alloc_descs_with_irq(data->dev, virq, nr_irqs, data);
+ if (err)
+ return err;
+
+ err = msi_domain_populate_irqs(domain->parent, data->dev,
+ virq, nr_irqs, &data->arg);
+ /* FIXME: memory leak on error */
+ return err;
+}
+
diff --git a/include/linux/msi.h b/include/linux/msi.h
index e35558c..594b2113 100644
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -172,6 +172,7 @@ struct msi_controller {
#include <asm/msi.h>
struct irq_domain;
+struct irq_domain_ops;
struct irq_chip;
struct device_node;
struct fwnode_handle;
@@ -283,6 +284,15 @@ int msi_domain_prepare_irqs(struct irq_domain *domain, struct device *dev,
int nvec, msi_alloc_info_t *args);
int msi_domain_populate_irqs(struct irq_domain *domain, struct device *dev,
int virq, int nvec, msi_alloc_info_t *args);
+struct irq_domain *
+platform_msi_create_device_domain(struct device *dev,
+ unsigned int nvec,
+ irq_write_msi_msg_t write_msi_msg,
+ const struct irq_domain_ops *ops,
+ void *host_data);
+int platform_msi_domain_alloc(struct irq_domain *domain, unsigned int virq,
+ unsigned int nr_irqs);
+void *platform_msi_get_host_data(struct irq_domain *domain);
#endif /* CONFIG_GENERIC_MSI_IRQ_DOMAIN */
#ifdef CONFIG_PCI_MSI_IRQ_DOMAIN
--
2.1.4
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH RFC 7/7] irqchip: [Example] dummy wired interrupt/MSI bridge driver
2015-10-15 15:39 [PATCH RFC 0/7] Adding core support for wire-MSI bridges Marc Zyngier
` (5 preceding siblings ...)
2015-10-15 15:39 ` [PATCH RFC 6/7] platform-msi: Allow creation of a MSI-based stacked irq domain Marc Zyngier
@ 2015-10-15 15:39 ` Marc Zyngier
2015-11-04 8:00 ` majun (F)
2015-10-15 15:46 ` [PATCH RFC 0/7] Adding core support for wire-MSI bridges Arnd Bergmann
2015-10-16 1:55 ` Jiang Liu
8 siblings, 1 reply; 30+ messages in thread
From: Marc Zyngier @ 2015-10-15 15:39 UTC (permalink / raw)
To: Thomas Gleixner, Jiang Liu, Jason Cooper
Cc: Ma Jun, linux-arm-kernel, linux-pci, linux-kernel
In order to demonstrate how to put together a wire/MSI bridge,
add a dummy driver that doesn't do anything at all, except
for allocating interrupts.
It comes together with an even more stupid client driver that
allocates an interrupt and dump the hierarchy of that interrupt.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
drivers/irqchip/Kconfig | 7 ++
drivers/irqchip/Makefile | 1 +
drivers/irqchip/irq-msichip.c | 271 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 279 insertions(+)
create mode 100644 drivers/irqchip/irq-msichip.c
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 4d7294e..73e38e6 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -193,3 +193,10 @@ config IRQ_MXS
def_bool y if MACH_ASM9260 || ARCH_MXS
select IRQ_DOMAIN
select STMP_DEVICE
+
+config DUMMY_MSICHIP
+ bool "Dummy irqchip on MSI"
+ depends on GENERIC_MSI_IRQ_DOMAIN
+ help
+ Dummy stacked irqchip on top of platform MSI
+
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 177f78f..682e7dc 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -55,3 +55,4 @@ obj-$(CONFIG_RENESAS_H8S_INTC) += irq-renesas-h8s.o
obj-$(CONFIG_ARCH_SA1100) += irq-sa11x0.o
obj-$(CONFIG_INGENIC_IRQ) += irq-ingenic.o
obj-$(CONFIG_IMX_GPCV2) += irq-imx-gpcv2.o
+obj-$(CONFIG_DUMMY_MSICHIP) += irq-msichip.o
diff --git a/drivers/irqchip/irq-msichip.c b/drivers/irqchip/irq-msichip.c
new file mode 100644
index 0000000..82b283b
--- /dev/null
+++ b/drivers/irqchip/irq-msichip.c
@@ -0,0 +1,271 @@
+/*
+ * Non-functionnal example for a wired irq <-> MSI bridge
+ *
+ * Copyright (C) 2015 ARM Limited, All Rights Reserved.
+ * Author: Marc Zyngier <marc.zyngier@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * DT fragment to represent the MSI bridge:
+
+ intc: msichip {
+ compatible = "dummy,msichip";
+ num-msis = 32;
+ interrupt-controller;
+ interrupt-parent = <&gic>;
+ #interrupt-cells = <0x2>;
+ msi-parent = <&its 1234>;
+ };
+
+ * DT fragment to represent the device connected to the bridge:
+
+ dummy-dev {
+ compatible = "dummy,device";
+ interrupt-parent = <intc>;
+ interrupts = <0x5 0x1>;
+ };
+
+ * When "dummy,device" gets probed, it dumps the hierarchy for the
+ * interrupt it has allocated:
+
+ dummydev dummy-dev: Allocated IRQ35
+ dummydev dummy-dev: Probing OK
+ dummydev dummy-dev: IRQ35 hwirq 5 domain msichip_domain_ops
+ dummydev dummy-dev: IRQ35 hwirq 0 domain msi_domain_ops
+ dummydev dummy-dev: IRQ35 hwirq 8192 domain its_domain_ops
+ dummydev dummy-dev: IRQ35 hwirq 8192 domain gic_irq_domain_ops
+ */
+
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqchip.h>
+#include <linux/irqdomain.h>
+#include <linux/module.h>
+#include <linux/msi.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+static void msichip_mask(struct irq_data *data)
+{
+ /* Do something */
+}
+
+static void msichip_unmask(struct irq_data *data)
+{
+ /* Do something */
+}
+
+static void msichip_eoi(struct irq_data *data)
+{
+ /* Do something */
+}
+
+static int msichip_set_type(struct irq_data *data, unsigned int type)
+{
+ /* Do something */
+ return 0;
+}
+
+static int msichip_retrigger(struct irq_data *data)
+{
+ /* Do something */
+ return 0;
+}
+
+static int msichip_set_affinity(struct irq_data *data,
+ const struct cpumask *dest, bool force)
+{
+ /* Do something */
+ return 0;
+}
+
+static struct irq_chip msichip_chip = {
+ .name = "MSICHIP",
+ .irq_mask = msichip_mask,
+ .irq_unmask = msichip_unmask,
+ .irq_eoi = msichip_eoi,
+ .irq_set_type = msichip_set_type,
+ .irq_retrigger = msichip_retrigger,
+ .irq_set_affinity = msichip_set_affinity,
+};
+
+static int msichip_domain_translate(struct irq_domain *d,
+ struct irq_fwspec *fwspec,
+ unsigned long *hwirq,
+ unsigned int *type)
+{
+ if (is_of_node(fwspec->fwnode)) {
+ if (fwspec->param_count != 2)
+ return -EINVAL;
+
+ *hwirq = fwspec->param[0];
+ *type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int msichip_domain_alloc(struct irq_domain *domain, unsigned int virq,
+ unsigned int nr_irqs, void *arg)
+{
+ int i, err;
+ irq_hw_number_t hwirq;
+ unsigned int type;
+ struct irq_fwspec *fwspec = arg;
+ void *data;
+
+ err = msichip_domain_translate(domain, fwspec, &hwirq, &type);
+ if (err)
+ return err;
+
+ err = platform_msi_domain_alloc(domain, virq, nr_irqs);
+ if (err)
+ return err;
+
+ data = platform_msi_get_host_data(domain);
+ for (i = 0; i < nr_irqs; i++)
+ irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
+ &msichip_chip, data);
+
+ return 0;
+}
+
+static const struct irq_domain_ops msichip_domain_ops = {
+ .translate = msichip_domain_translate,
+ .alloc = msichip_domain_alloc,
+ .free = irq_domain_free_irqs_common,
+};
+
+struct msichip_data {
+ /* Add whatever you fancy here */
+ struct platform_device *pdev;
+};
+
+static void msichip_write_msi_msg(struct msi_desc *desc, struct msi_msg *msg)
+{
+ /* Do the right thing */
+}
+
+static int msichip_probe(struct platform_device *pdev)
+{
+ struct irq_domain *domain;
+ struct msichip_data *msichip_data;
+ u32 num_msis;
+
+ dev_info(&pdev->dev, "Probing\n");
+ msichip_data = kzalloc(sizeof(*msichip_data), GFP_KERNEL);
+ if (!msichip_data)
+ return -ENOMEM;
+
+ msichip_data->pdev = pdev;
+
+ /* If there is no "num-msi" property, assume 64... */
+ if (of_property_read_u32(pdev->dev.of_node, "num-msis", &num_msis) < 0)
+ num_msis = 64;
+
+ dev_info(&pdev->dev, "allocating %d MSIs\n", num_msis);
+
+ domain = platform_msi_create_device_domain(&pdev->dev, num_msis,
+ msichip_write_msi_msg,
+ &msichip_domain_ops,
+ msichip_data);
+
+ if (!domain){
+ kfree(msichip_data);
+ return -ENOMEM;
+ }
+
+ dev_info(&pdev->dev, "Probing OK\n");
+ return 0;
+}
+
+static const struct of_device_id msichip_of_match[] = {
+ { .compatible = "dummy,msichip", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, msichip_of_match);
+
+static struct platform_driver msichip_driver = {
+ .driver = {
+ .name = "msichip",
+ .of_match_table = msichip_of_match,
+ },
+ .probe = msichip_probe,
+};
+/* Do not define this as an irqchip */
+module_platform_driver(msichip_driver);
+
+
+
+/* Driver for a dummy device connected to the MSI bridge */
+static irqreturn_t dummydev_handler(int irq, void *dummy)
+{
+ return IRQ_HANDLED;
+}
+
+static void dummydev_dump_hierarchy(struct device *dev, int irq)
+{
+ struct irq_data *data = irq_get_irq_data(irq);
+
+ while(data) {
+ dev_info(dev, "IRQ%d hwirq %d domain %ps\n",
+ data->irq, (int)data->hwirq, data->domain->ops);
+ data = data->parent_data;
+ }
+}
+
+static int dummydev_probe(struct platform_device *pdev)
+{
+ int irq;
+
+ dev_info(&pdev->dev, "Probing\n");
+ irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
+ if (!irq) {
+ dev_err(&pdev->dev, "irq allocation failed, defering\n");
+ return -EPROBE_DEFER;
+ }
+
+ dev_info(&pdev->dev, "Allocated IRQ%d\n", irq);
+
+ if (request_irq(irq, dummydev_handler, 0, "dummydev", pdev))
+ return -EINVAL;
+
+ dev_info(&pdev->dev, "Probing OK\n");
+
+ dummydev_dump_hierarchy(&pdev->dev, irq);
+ return 0;
+}
+
+static const struct of_device_id dummydev_of_match[] = {
+ { .compatible = "dummy,device", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, dummydev_of_match);
+
+static struct platform_driver dummydev_driver = {
+ .driver = {
+ .name = "dummydev",
+ .of_match_table = dummydev_of_match,
+ },
+ .probe = dummydev_probe,
+};
+
+module_platform_driver(dummydev_driver);
--
2.1.4
^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: [PATCH RFC 7/7] irqchip: [Example] dummy wired interrupt/MSI bridge driver
2015-10-15 15:39 ` [PATCH RFC 7/7] irqchip: [Example] dummy wired interrupt/MSI bridge driver Marc Zyngier
@ 2015-11-04 8:00 ` majun (F)
2015-11-04 9:03 ` Marc Zyngier
0 siblings, 1 reply; 30+ messages in thread
From: majun (F) @ 2015-11-04 8:00 UTC (permalink / raw)
To: Marc Zyngier, Thomas Gleixner, Jiang Liu, Jason Cooper
Cc: linux-arm-kernel, linux-pci, linux-kernel
Hi Marc:
在 2015/10/15 23:39, Marc Zyngier 写道:
> In order to demonstrate how to put together a wire/MSI bridge,
> add a dummy driver that doesn't do anything at all, except
> for allocating interrupts.
>
> It comes together with an even more stupid client driver that
> allocates an interrupt and dump the hierarchy of that interrupt.
>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
[...]
> +
> +static int msichip_domain_alloc(struct irq_domain *domain, unsigned int virq,
> + unsigned int nr_irqs, void *arg)
> +{
> + int i, err;
> + irq_hw_number_t hwirq;
> + unsigned int type;
> + struct irq_fwspec *fwspec = arg;
> + void *data;
> +
> + err = msichip_domain_translate(domain, fwspec, &hwirq, &type);
> + if (err)
> + return err;
> +
.translate function already called once in irq_domain_translate(),
I think we don't need call this fucntion one more time here.
> + err = platform_msi_domain_alloc(domain, virq, nr_irqs);
> + if (err)
> + return err;
> +
> + data = platform_msi_get_host_data(domain);
> + for (i = 0; i < nr_irqs; i++)
> + irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
> + &msichip_chip, data);
> +
> + return 0;
> +}
> +
[...]
> +
> +static struct platform_driver msichip_driver = {
> + .driver = {
> + .name = "msichip",
> + .of_match_table = msichip_of_match,
> + },
> + .probe = msichip_probe,
> +};
> +/* Do not define this as an irqchip */
> +module_platform_driver(msichip_driver);
> +
> +
I think,for a interrupt controller, msichip driver initialization maybe is too late
for some devices which connect to this irqchip if we use module_platform_driver.
So, how about use the arch_initcall to register the msichip driver?
Thanks!
Ma Jun
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH RFC 7/7] irqchip: [Example] dummy wired interrupt/MSI bridge driver
2015-11-04 8:00 ` majun (F)
@ 2015-11-04 9:03 ` Marc Zyngier
2015-11-05 8:25 ` Gabriele Paoloni
0 siblings, 1 reply; 30+ messages in thread
From: Marc Zyngier @ 2015-11-04 9:03 UTC (permalink / raw)
To: majun (F), Thomas Gleixner, Jiang Liu, Jason Cooper
Cc: linux-arm-kernel, linux-pci, linux-kernel
On 04/11/15 08:00, majun (F) wrote:
> Hi Marc:
>
> 在 2015/10/15 23:39, Marc Zyngier 写道:
>> In order to demonstrate how to put together a wire/MSI bridge,
>> add a dummy driver that doesn't do anything at all, except
>> for allocating interrupts.
>>
>> It comes together with an even more stupid client driver that
>> allocates an interrupt and dump the hierarchy of that interrupt.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
> [...]
>> +
>> +static int msichip_domain_alloc(struct irq_domain *domain, unsigned int virq,
>> + unsigned int nr_irqs, void *arg)
>> +{
>> + int i, err;
>> + irq_hw_number_t hwirq;
>> + unsigned int type;
>> + struct irq_fwspec *fwspec = arg;
>> + void *data;
>> +
>> + err = msichip_domain_translate(domain, fwspec, &hwirq, &type);
>> + if (err)
>> + return err;
>> +
>
> .translate function already called once in irq_domain_translate(),
> I think we don't need call this fucntion one more time here.
if you don't translate it here, how do you obtain the hwirq that you
have to pass to irq_domain_set_hwirq_and_chip just below?
>> + err = platform_msi_domain_alloc(domain, virq, nr_irqs);
>> + if (err)
>> + return err;
>> +
>> + data = platform_msi_get_host_data(domain);
>> + for (i = 0; i < nr_irqs; i++)
>> + irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
>> + &msichip_chip, data);
>> +
>> + return 0;
>> +}
>> +
> [...]
>> +
>> +static struct platform_driver msichip_driver = {
>> + .driver = {
>> + .name = "msichip",
>> + .of_match_table = msichip_of_match,
>> + },
>> + .probe = msichip_probe,
>> +};
>> +/* Do not define this as an irqchip */
>> +module_platform_driver(msichip_driver);
>> +
>> +
>
> I think,for a interrupt controller, msichip driver initialization maybe is too late
> for some devices which connect to this irqchip if we use module_platform_driver.
That's a consequence of this design. This is why I insisted on the fact
that this is currently avoided by using deferred probe in drivers, and
that it should be solved by having a probe order. Either way, this is
not something that we can solve at that level (see the multiple proposal
for this on the various lists).
> So, how about use the arch_initcall to register the msichip driver?
You're only pushing the problem one level up. And you'll realize that
this is not enough for some random driver. This is not sustainable, and
must be addressed properly.
Thanks,
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply [flat|nested] 30+ messages in thread
* RE: [PATCH RFC 7/7] irqchip: [Example] dummy wired interrupt/MSI bridge driver
2015-11-04 9:03 ` Marc Zyngier
@ 2015-11-05 8:25 ` Gabriele Paoloni
2015-11-05 9:35 ` Marc Zyngier
0 siblings, 1 reply; 30+ messages in thread
From: Gabriele Paoloni @ 2015-11-05 8:25 UTC (permalink / raw)
To: Marc Zyngier, majun (F), Thomas Gleixner, Jiang Liu, Jason Cooper
Cc: linux-arm-kernel@lists.infradead.org, linux-pci@vger.kernel.org,
linux-kernel@vger.kernel.org
SGkgTWFyYw0KDQo+IC0tLS0tT3JpZ2luYWwgTWVzc2FnZS0tLS0tDQo+IEZyb206IGxpbnV4LXBj
aS1vd25lckB2Z2VyLmtlcm5lbC5vcmcgW21haWx0bzpsaW51eC1wY2ktb3duZXJAdmdlci5rZXJu
ZWwub3JnXQ0KPiBPbiBCZWhhbGYgT2YgTWFyYyBaeW5naWVyDQo+IFNlbnQ6IDA0IE5vdmVtYmVy
IDIwMTUgMDk6MDQNCj4gVG86IG1hanVuIChGKTsgVGhvbWFzIEdsZWl4bmVyOyBKaWFuZyBMaXU7
IEphc29uIENvb3Blcg0KPiBDYzogbGludXgtYXJtLWtlcm5lbEBsaXN0cy5pbmZyYWRlYWQub3Jn
OyBsaW51eC1wY2lAdmdlci5rZXJuZWwub3JnOyBsaW51eC0NCj4ga2VybmVsQHZnZXIua2VybmVs
Lm9yZw0KPiBTdWJqZWN0OiBSZTogW1BBVENIIFJGQyA3LzddIGlycWNoaXA6IFtFeGFtcGxlXSBk
dW1teSB3aXJlZCBpbnRlcnJ1cHQvTVNJDQo+IGJyaWRnZSBkcml2ZXINCj4gDQo+IE9uIDA0LzEx
LzE1IDA4OjAwLCBtYWp1biAoRikgd3JvdGU6DQo+ID4gSGkgTWFyYzoNCj4gPg0KPiA+INTaIDIw
MTUvMTAvMTUgMjM6MzksIE1hcmMgWnluZ2llciDQtLXAOg0KPiA+PiBJbiBvcmRlciB0byBkZW1v
bnN0cmF0ZSBob3cgdG8gcHV0IHRvZ2V0aGVyIGEgd2lyZS9NU0kgYnJpZGdlLA0KPiA+PiBhZGQg
YSBkdW1teSBkcml2ZXIgdGhhdCBkb2Vzbid0IGRvIGFueXRoaW5nIGF0IGFsbCwgZXhjZXB0DQo+
ID4+IGZvciBhbGxvY2F0aW5nIGludGVycnVwdHMuDQo+ID4+DQo+ID4+IEl0IGNvbWVzIHRvZ2V0
aGVyIHdpdGggYW4gZXZlbiBtb3JlIHN0dXBpZCBjbGllbnQgZHJpdmVyIHRoYXQNCj4gPj4gYWxs
b2NhdGVzIGFuIGludGVycnVwdCBhbmQgZHVtcCB0aGUgaGllcmFyY2h5IG9mIHRoYXQgaW50ZXJy
dXB0Lg0KPiA+Pg0KPiA+PiBTaWduZWQtb2ZmLWJ5OiBNYXJjIFp5bmdpZXIgPG1hcmMuenluZ2ll
ckBhcm0uY29tPg0KPiA+PiAtLS0NCj4gPiBbLi4uXQ0KPiA+PiArDQo+ID4+ICtzdGF0aWMgaW50
IG1zaWNoaXBfZG9tYWluX2FsbG9jKHN0cnVjdCBpcnFfZG9tYWluICpkb21haW4sIHVuc2lnbmVk
IGludA0KPiB2aXJxLA0KPiA+PiArCQkJCSAgIHVuc2lnbmVkIGludCBucl9pcnFzLCB2b2lkICph
cmcpDQo+ID4+ICt7DQo+ID4+ICsJaW50IGksIGVycjsNCj4gPj4gKwlpcnFfaHdfbnVtYmVyX3Qg
aHdpcnE7DQo+ID4+ICsJdW5zaWduZWQgaW50IHR5cGU7DQo+ID4+ICsJc3RydWN0IGlycV9md3Nw
ZWMgKmZ3c3BlYyA9IGFyZzsNCj4gPj4gKwl2b2lkICpkYXRhOw0KPiA+PiArDQo+ID4+ICsJZXJy
ID0gbXNpY2hpcF9kb21haW5fdHJhbnNsYXRlKGRvbWFpbiwgZndzcGVjLCAmaHdpcnEsICZ0eXBl
KTsNCj4gPj4gKwlpZiAoZXJyKQ0KPiA+PiArCQlyZXR1cm4gZXJyOw0KPiA+PiArDQo+ID4NCj4g
PiAudHJhbnNsYXRlIGZ1bmN0aW9uIGFscmVhZHkgY2FsbGVkIG9uY2UgaW4gIGlycV9kb21haW5f
dHJhbnNsYXRlKCksDQo+ID4gSSB0aGluayB3ZSBkb24ndCBuZWVkIGNhbGwgdGhpcyBmdWNudGlv
biBvbmUgbW9yZSB0aW1lIGhlcmUuDQo+IA0KPiBpZiB5b3UgZG9uJ3QgdHJhbnNsYXRlIGl0IGhl
cmUsIGhvdyBkbyB5b3Ugb2J0YWluIHRoZSBod2lycSB0aGF0IHlvdQ0KPiBoYXZlIHRvIHBhc3Mg
dG8gaXJxX2RvbWFpbl9zZXRfaHdpcnFfYW5kX2NoaXAganVzdCBiZWxvdz8NCj4gDQo+ID4+ICsJ
ZXJyID0gcGxhdGZvcm1fbXNpX2RvbWFpbl9hbGxvYyhkb21haW4sIHZpcnEsIG5yX2lycXMpOw0K
PiA+PiArCWlmIChlcnIpDQo+ID4+ICsJCXJldHVybiBlcnI7DQo+ID4+ICsNCj4gPj4gKwlkYXRh
ID0gcGxhdGZvcm1fbXNpX2dldF9ob3N0X2RhdGEoZG9tYWluKTsNCj4gPj4gKwlmb3IgKGkgPSAw
OyBpIDwgbnJfaXJxczsgaSsrKQ0KPiA+PiArCQlpcnFfZG9tYWluX3NldF9od2lycV9hbmRfY2hp
cChkb21haW4sIHZpcnEgKyBpLCBod2lycSArIGksDQo+ID4+ICsJCQkJCSAgICAgICZtc2ljaGlw
X2NoaXAsIGRhdGEpOw0KPiA+PiArDQo+ID4+ICsJcmV0dXJuIDA7DQo+ID4+ICt9DQo+ID4+ICsN
Cj4gPiBbLi4uXQ0KPiA+PiArDQo+ID4+ICtzdGF0aWMgc3RydWN0IHBsYXRmb3JtX2RyaXZlciBt
c2ljaGlwX2RyaXZlciA9IHsNCj4gPj4gKwkuZHJpdmVyID0gew0KPiA+PiArCQkubmFtZQkJPSAi
bXNpY2hpcCIsDQo+ID4+ICsJCS5vZl9tYXRjaF90YWJsZQk9IG1zaWNoaXBfb2ZfbWF0Y2gsDQo+
ID4+ICsJfSwNCj4gPj4gKwkucHJvYmUJCQk9IG1zaWNoaXBfcHJvYmUsDQo+ID4+ICt9Ow0KPiA+
PiArLyogRG8gbm90IGRlZmluZSB0aGlzIGFzIGFuIGlycWNoaXAgKi8NCj4gPj4gK21vZHVsZV9w
bGF0Zm9ybV9kcml2ZXIobXNpY2hpcF9kcml2ZXIpOw0KPiA+PiArDQo+ID4+ICsNCj4gPg0KPiA+
IEkgdGhpbmssZm9yIGEgaW50ZXJydXB0IGNvbnRyb2xsZXIsIG1zaWNoaXAgZHJpdmVyIGluaXRp
YWxpemF0aW9uIG1heWJlIGlzDQo+IHRvbyBsYXRlDQo+ID4gZm9yIHNvbWUgZGV2aWNlcyB3aGlj
aCBjb25uZWN0IHRvIHRoaXMgaXJxY2hpcCBpZiB3ZSB1c2UNCj4gbW9kdWxlX3BsYXRmb3JtX2Ry
aXZlci4NCj4gDQo+IFRoYXQncyBhIGNvbnNlcXVlbmNlIG9mIHRoaXMgZGVzaWduLiBUaGlzIGlz
IHdoeSBJIGluc2lzdGVkIG9uIHRoZSBmYWN0DQo+IHRoYXQgdGhpcyBpcyBjdXJyZW50bHkgYXZv
aWRlZCBieSB1c2luZyBkZWZlcnJlZCBwcm9iZSBpbiBkcml2ZXJzLCBhbmQNCg0KTW1tIHVzaW5n
IHRlIGRlZmVycmVkIHByb2JlIHdvdWxkIG1lYW4gdG8gcmV3b3JrIGFsbCB0aGUgZHJpdmVycyBv
ZiB0aGUNCnBvdGVudGlhbCBkZXZpY2VzIGNvbm5lY3RlZCB0byBtYmktZ2VuLi4ud291bGQgdGhh
dCBiZSBzdXN0YWluYWJsZS9hY2NlcHRhYmxlPw0KDQo+IHRoYXQgaXQgc2hvdWxkIGJlIHNvbHZl
ZCBieSBoYXZpbmcgYSBwcm9iZSBvcmRlci4gRWl0aGVyIHdheSwgdGhpcyBpcw0KPiBub3Qgc29t
ZXRoaW5nIHRoYXQgd2UgY2FuIHNvbHZlIGF0IHRoYXQgbGV2ZWwgKHNlZSB0aGUgbXVsdGlwbGUg
cHJvcG9zYWwNCj4gZm9yIHRoaXMgb24gdGhlIHZhcmlvdXMgbGlzdHMpLg0KDQpDb3VsZCB5b3Ug
cG9pbnQgbWUgdG8gdGhlIHJlbGV2YW50IGRpc2N1c3Npb25zIGZvciB0aGlzLi4uPw0KDQpUaGFu
a3MNCg0KR2FiDQoNCj4gDQo+ID4gU28sIGhvdyBhYm91dCB1c2UgdGhlIGFyY2hfaW5pdGNhbGwg
dG8gcmVnaXN0ZXIgdGhlIG1zaWNoaXAgZHJpdmVyPw0KPiANCj4gWW91J3JlIG9ubHkgcHVzaGlu
ZyB0aGUgcHJvYmxlbSBvbmUgbGV2ZWwgdXAuIEFuZCB5b3UnbGwgcmVhbGl6ZSB0aGF0DQo+IHRo
aXMgaXMgbm90IGVub3VnaCBmb3Igc29tZSByYW5kb20gZHJpdmVyLiBUaGlzIGlzIG5vdCBzdXN0
YWluYWJsZSwgYW5kDQo+IG11c3QgYmUgYWRkcmVzc2VkIHByb3Blcmx5Lg0KPiANCj4gVGhhbmtz
LA0KPiANCj4gCU0uDQo+IC0tDQo+IEphenogaXMgbm90IGRlYWQuIEl0IGp1c3Qgc21lbGxzIGZ1
bm55Li4uDQo+IC0tDQo+IFRvIHVuc3Vic2NyaWJlIGZyb20gdGhpcyBsaXN0OiBzZW5kIHRoZSBs
aW5lICJ1bnN1YnNjcmliZSBsaW51eC1wY2kiIGluDQo+IHRoZSBib2R5IG9mIGEgbWVzc2FnZSB0
byBtYWpvcmRvbW9Admdlci5rZXJuZWwub3JnDQo+IE1vcmUgbWFqb3Jkb21vIGluZm8gYXQgIGh0
dHA6Ly92Z2VyLmtlcm5lbC5vcmcvbWFqb3Jkb21vLWluZm8uaHRtbA0K
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH RFC 7/7] irqchip: [Example] dummy wired interrupt/MSI bridge driver
2015-11-05 8:25 ` Gabriele Paoloni
@ 2015-11-05 9:35 ` Marc Zyngier
2015-11-05 9:43 ` Gabriele Paoloni
0 siblings, 1 reply; 30+ messages in thread
From: Marc Zyngier @ 2015-11-05 9:35 UTC (permalink / raw)
To: Gabriele Paoloni, majun (F), Thomas Gleixner, Jiang Liu,
Jason Cooper
Cc: linux-arm-kernel@lists.infradead.org, linux-pci@vger.kernel.org,
linux-kernel@vger.kernel.org
On 05/11/15 08:25, Gabriele Paoloni wrote:
> Hi Marc
>
>> -----Original Message-----
>> From: linux-pci-owner@vger.kernel.org [mailto:linux-pci-owner@vger.kernel.org]
>> On Behalf Of Marc Zyngier
>> Sent: 04 November 2015 09:04
>> To: majun (F); Thomas Gleixner; Jiang Liu; Jason Cooper
>> Cc: linux-arm-kernel@lists.infradead.org; linux-pci@vger.kernel.org; linux-
>> kernel@vger.kernel.org
>> Subject: Re: [PATCH RFC 7/7] irqchip: [Example] dummy wired interrupt/MSI
>> bridge driver
>>
>> On 04/11/15 08:00, majun (F) wrote:
[...]
>>> I think,for a interrupt controller, msichip driver initialization maybe is
>> too late
>>> for some devices which connect to this irqchip if we use
>> module_platform_driver.
>>
>> That's a consequence of this design. This is why I insisted on the fact
>> that this is currently avoided by using deferred probe in drivers, and
>
> Mmm using te deferred probe would mean to rework all the drivers of the
> potential devices connected to mbi-gen...would that be sustainable/acceptable?
I'm tempted to reply "Not my problem". Or rather, not a problem I'm
trying to solve right now (or any time soon).
I'm pretty sure that sprinkling -EPROBE_DEFER on all possible drivers
will result in a resounding NAK, which is is why I suggested that
someone with a vested interest dedicates some quality time helping those
who are trying to solve this issue for good.
>> that it should be solved by having a probe order. Either way, this is
>> not something that we can solve at that level (see the multiple proposal
>> for this on the various lists).
>
> Could you point me to the relevant discussions for this...?
Google is, as always, your dearest friend. But here you go:
- LWN has some quality coverage of the KS discussions (assuming you're a
subscriber, otherwise you'll have to wait for another week):
http://lwn.net/Articles/662820/
- There is also Tomeu Vizoso's series, which itself builds upon other
previous attempts at solving this: https://lwn.net/Articles/658690/
Thanks,
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply [flat|nested] 30+ messages in thread
* RE: [PATCH RFC 7/7] irqchip: [Example] dummy wired interrupt/MSI bridge driver
2015-11-05 9:35 ` Marc Zyngier
@ 2015-11-05 9:43 ` Gabriele Paoloni
0 siblings, 0 replies; 30+ messages in thread
From: Gabriele Paoloni @ 2015-11-05 9:43 UTC (permalink / raw)
To: Marc Zyngier, majun (F), Thomas Gleixner, Jiang Liu, Jason Cooper
Cc: linux-arm-kernel@lists.infradead.org, linux-pci@vger.kernel.org,
linux-kernel@vger.kernel.org
PiAtLS0tLU9yaWdpbmFsIE1lc3NhZ2UtLS0tLQ0KPiBGcm9tOiBNYXJjIFp5bmdpZXIgW21haWx0
bzptYXJjLnp5bmdpZXJAYXJtLmNvbV0NCj4gU2VudDogVGh1cnNkYXksIE5vdmVtYmVyIDA1LCAy
MDE1IDk6MzYgQU0NCj4gVG86IEdhYnJpZWxlIFBhb2xvbmk7IG1hanVuIChGKTsgVGhvbWFzIEds
ZWl4bmVyOyBKaWFuZyBMaXU7IEphc29uDQo+IENvb3Blcg0KPiBDYzogbGludXgtYXJtLWtlcm5l
bEBsaXN0cy5pbmZyYWRlYWQub3JnOyBsaW51eC1wY2lAdmdlci5rZXJuZWwub3JnOw0KPiBsaW51
eC1rZXJuZWxAdmdlci5rZXJuZWwub3JnDQo+IFN1YmplY3Q6IFJlOiBbUEFUQ0ggUkZDIDcvN10g
aXJxY2hpcDogW0V4YW1wbGVdIGR1bW15IHdpcmVkDQo+IGludGVycnVwdC9NU0kgYnJpZGdlIGRy
aXZlcg0KPiANCj4gT24gMDUvMTEvMTUgMDg6MjUsIEdhYnJpZWxlIFBhb2xvbmkgd3JvdGU6DQo+
ID4gSGkgTWFyYw0KPiA+DQo+ID4+IC0tLS0tT3JpZ2luYWwgTWVzc2FnZS0tLS0tDQo+ID4+IEZy
b206IGxpbnV4LXBjaS1vd25lckB2Z2VyLmtlcm5lbC5vcmcgW21haWx0bzpsaW51eC1wY2ktDQo+
IG93bmVyQHZnZXIua2VybmVsLm9yZ10NCj4gPj4gT24gQmVoYWxmIE9mIE1hcmMgWnluZ2llcg0K
PiA+PiBTZW50OiAwNCBOb3ZlbWJlciAyMDE1IDA5OjA0DQo+ID4+IFRvOiBtYWp1biAoRik7IFRo
b21hcyBHbGVpeG5lcjsgSmlhbmcgTGl1OyBKYXNvbiBDb29wZXINCj4gPj4gQ2M6IGxpbnV4LWFy
bS1rZXJuZWxAbGlzdHMuaW5mcmFkZWFkLm9yZzsgbGludXgtcGNpQHZnZXIua2VybmVsLm9yZzsN
Cj4gbGludXgtDQo+ID4+IGtlcm5lbEB2Z2VyLmtlcm5lbC5vcmcNCj4gPj4gU3ViamVjdDogUmU6
IFtQQVRDSCBSRkMgNy83XSBpcnFjaGlwOiBbRXhhbXBsZV0gZHVtbXkgd2lyZWQNCj4gaW50ZXJy
dXB0L01TSQ0KPiA+PiBicmlkZ2UgZHJpdmVyDQo+ID4+DQo+ID4+IE9uIDA0LzExLzE1IDA4OjAw
LCBtYWp1biAoRikgd3JvdGU6DQo+IA0KPiBbLi4uXQ0KPiANCj4gPj4+IEkgdGhpbmssZm9yIGEg
aW50ZXJydXB0IGNvbnRyb2xsZXIsIG1zaWNoaXAgZHJpdmVyIGluaXRpYWxpemF0aW9uDQo+IG1h
eWJlIGlzDQo+ID4+IHRvbyBsYXRlDQo+ID4+PiBmb3Igc29tZSBkZXZpY2VzIHdoaWNoIGNvbm5l
Y3QgdG8gdGhpcyBpcnFjaGlwIGlmIHdlIHVzZQ0KPiA+PiBtb2R1bGVfcGxhdGZvcm1fZHJpdmVy
Lg0KPiA+Pg0KPiA+PiBUaGF0J3MgYSBjb25zZXF1ZW5jZSBvZiB0aGlzIGRlc2lnbi4gVGhpcyBp
cyB3aHkgSSBpbnNpc3RlZCBvbiB0aGUNCj4gZmFjdA0KPiA+PiB0aGF0IHRoaXMgaXMgY3VycmVu
dGx5IGF2b2lkZWQgYnkgdXNpbmcgZGVmZXJyZWQgcHJvYmUgaW4gZHJpdmVycywNCj4gYW5kDQo+
ID4NCj4gPiBNbW0gdXNpbmcgdGUgZGVmZXJyZWQgcHJvYmUgd291bGQgbWVhbiB0byByZXdvcmsg
YWxsIHRoZSBkcml2ZXJzIG9mDQo+IHRoZQ0KPiA+IHBvdGVudGlhbCBkZXZpY2VzIGNvbm5lY3Rl
ZCB0byBtYmktZ2VuLi4ud291bGQgdGhhdCBiZQ0KPiBzdXN0YWluYWJsZS9hY2NlcHRhYmxlPw0K
PiANCj4gSSdtIHRlbXB0ZWQgdG8gcmVwbHkgIk5vdCBteSBwcm9ibGVtIi4gT3IgcmF0aGVyLCBu
b3QgYSBwcm9ibGVtIEknbQ0KPiB0cnlpbmcgdG8gc29sdmUgcmlnaHQgbm93IChvciBhbnkgdGlt
ZSBzb29uKS4NCj4gDQo+IEknbSBwcmV0dHkgc3VyZSB0aGF0IHNwcmlua2xpbmcgLUVQUk9CRV9E
RUZFUiBvbiBhbGwgcG9zc2libGUgZHJpdmVycw0KPiB3aWxsIHJlc3VsdCBpbiBhIHJlc291bmRp
bmcgTkFLLCB3aGljaCBpcyBpcyB3aHkgSSBzdWdnZXN0ZWQgdGhhdA0KPiBzb21lb25lIHdpdGgg
YSB2ZXN0ZWQgaW50ZXJlc3QgZGVkaWNhdGVzIHNvbWUgcXVhbGl0eSB0aW1lIGhlbHBpbmcNCj4g
dGhvc2UNCj4gd2hvIGFyZSB0cnlpbmcgdG8gc29sdmUgdGhpcyBpc3N1ZSBmb3IgZ29vZC4NCg0K
WWVzIHlvdSdyZSByaWdodCwgbWFrZXMgcGVyZmVjdCBzZW5zZQ0KDQo+IA0KPiA+PiB0aGF0IGl0
IHNob3VsZCBiZSBzb2x2ZWQgYnkgaGF2aW5nIGEgcHJvYmUgb3JkZXIuIEVpdGhlciB3YXksIHRo
aXMNCj4gaXMNCj4gPj4gbm90IHNvbWV0aGluZyB0aGF0IHdlIGNhbiBzb2x2ZSBhdCB0aGF0IGxl
dmVsIChzZWUgdGhlIG11bHRpcGxlDQo+IHByb3Bvc2FsDQo+ID4+IGZvciB0aGlzIG9uIHRoZSB2
YXJpb3VzIGxpc3RzKS4NCj4gPg0KPiA+IENvdWxkIHlvdSBwb2ludCBtZSB0byB0aGUgcmVsZXZh
bnQgZGlzY3Vzc2lvbnMgZm9yIHRoaXMuLi4/DQo+IA0KPiBHb29nbGUgaXMsIGFzIGFsd2F5cywg
eW91ciBkZWFyZXN0IGZyaWVuZC4gQnV0IGhlcmUgeW91IGdvOg0KPiANCj4gLSBMV04gaGFzIHNv
bWUgcXVhbGl0eSBjb3ZlcmFnZSBvZiB0aGUgS1MgZGlzY3Vzc2lvbnMgKGFzc3VtaW5nIHlvdSdy
ZQ0KPiBhDQo+IHN1YnNjcmliZXIsIG90aGVyd2lzZSB5b3UnbGwgaGF2ZSB0byB3YWl0IGZvciBh
bm90aGVyIHdlZWspOg0KPiBodHRwOi8vbHduLm5ldC9BcnRpY2xlcy82NjI4MjAvDQo+IA0KPiAt
IFRoZXJlIGlzIGFsc28gVG9tZXUgVml6b3NvJ3Mgc2VyaWVzLCB3aGljaCBpdHNlbGYgYnVpbGRz
IHVwb24gb3RoZXINCj4gcHJldmlvdXMgYXR0ZW1wdHMgYXQgc29sdmluZyB0aGlzOiBodHRwczov
L2x3bi5uZXQvQXJ0aWNsZXMvNjU4NjkwLw0KPiANCg0KR3JlYXQsIG1hbnkgdGhhbmtzIGZvciBw
b2ludGluZyB0aGVtIG91dC4NCg0KSSdsbCBsb29rIGludG8gdGhlc2UuDQoNClRoYW5rcyBhZ2Fp
bg0KDQpHYWINCg0KPiBUaGFua3MsDQo+IA0KPiAJTS4NCj4gLS0NCj4gSmF6eiBpcyBub3QgZGVh
ZC4gSXQganVzdCBzbWVsbHMgZnVubnkuLi4NCg==
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH RFC 0/7] Adding core support for wire-MSI bridges
2015-10-15 15:39 [PATCH RFC 0/7] Adding core support for wire-MSI bridges Marc Zyngier
` (6 preceding siblings ...)
2015-10-15 15:39 ` [PATCH RFC 7/7] irqchip: [Example] dummy wired interrupt/MSI bridge driver Marc Zyngier
@ 2015-10-15 15:46 ` Arnd Bergmann
2015-10-15 16:01 ` Marc Zyngier
2015-10-16 1:55 ` Jiang Liu
8 siblings, 1 reply; 30+ messages in thread
From: Arnd Bergmann @ 2015-10-15 15:46 UTC (permalink / raw)
To: linux-arm-kernel
Cc: Marc Zyngier, Thomas Gleixner, Jiang Liu, Jason Cooper, linux-pci,
linux-kernel, Ma Jun
On Thursday 15 October 2015 16:39:21 Marc Zyngier wrote:
> There seems to be a new class of interrupt controller out there whose
> sole purpose (apart from making everybody's life a nightmare) is to
> turn wired interrupts into MSIs.
>
> Instead of considering that the MSIs allocated to a device are for the
> direct use of that device, we can turn this set of MSIs into a irq
> domain, and use that domain to build a standard irqchip on top of
> that.
>
> This requires some (slightly ugly) surgery in both the generic MSI and
> platform MSI layers, but the amount of code is actually relatively
> small (about +150 LoC so far).
>
> On top of that, we add a dummy driver for a such a bridge, hoping that
> this will give enough information to driver authors so that they can
> use this new feature. An even more stupid client driver is provided to
> show the interrupt stack allocation:
I'm pretty sure you've thought of this before and it doesn't work, but
can you explain why we can't just treat this as an edge-triggered
nested irqchip? As long as the weird hardware can be preconfigured
by the bootloader, the device that is attached to it shouldn't
care how the interrupt ends up at the CPU.
Arnd
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH RFC 0/7] Adding core support for wire-MSI bridges
2015-10-15 15:46 ` [PATCH RFC 0/7] Adding core support for wire-MSI bridges Arnd Bergmann
@ 2015-10-15 16:01 ` Marc Zyngier
2015-10-15 19:16 ` Arnd Bergmann
0 siblings, 1 reply; 30+ messages in thread
From: Marc Zyngier @ 2015-10-15 16:01 UTC (permalink / raw)
To: Arnd Bergmann, linux-arm-kernel
Cc: Thomas Gleixner, Jiang Liu, Jason Cooper, linux-pci, linux-kernel,
Ma Jun
Hi Arnd,
On 15/10/15 16:46, Arnd Bergmann wrote:
> On Thursday 15 October 2015 16:39:21 Marc Zyngier wrote:
>> There seems to be a new class of interrupt controller out there whose
>> sole purpose (apart from making everybody's life a nightmare) is to
>> turn wired interrupts into MSIs.
>>
>> Instead of considering that the MSIs allocated to a device are for the
>> direct use of that device, we can turn this set of MSIs into a irq
>> domain, and use that domain to build a standard irqchip on top of
>> that.
>>
>> This requires some (slightly ugly) surgery in both the generic MSI and
>> platform MSI layers, but the amount of code is actually relatively
>> small (about +150 LoC so far).
>>
>> On top of that, we add a dummy driver for a such a bridge, hoping that
>> this will give enough information to driver authors so that they can
>> use this new feature. An even more stupid client driver is provided to
>> show the interrupt stack allocation:
>
> I'm pretty sure you've thought of this before and it doesn't work, but
> can you explain why we can't just treat this as an edge-triggered
> nested irqchip? As long as the weird hardware can be preconfigured
> by the bootloader, the device that is attached to it shouldn't
> care how the interrupt ends up at the CPU.
"Preconfigured" is the key word. While you can do something like that if
your hardware treats MSIs just as if they were wired interrupts
(something like GICv2m), it becomes far more hairy if the target of MSIs
is something like a GICv3 ITS (which is the case for HiSilicon mbigen).
The main reason is that the ITS relies on "translation tables" kept in
memory, which the OS has to configure, and handing over pre-configured
tables is not something I'm looking forward to doing. From a CPU point
of view, this is akin entering the kernel with the MMU already on and no
idmap...
The approach taken here is to make the MSI-ness explicit at the irqchip
level, and keep the interrupting device oblivious of that feature. Also,
this relies on the fact that we can have one MSI per wire, meaning that
we don't have to multiplex anything (no nested irqchip), and that we can
rely on hierarchical domains, which simplifies the code (at least for
the irqchip).
Thanks,
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH RFC 0/7] Adding core support for wire-MSI bridges
2015-10-15 16:01 ` Marc Zyngier
@ 2015-10-15 19:16 ` Arnd Bergmann
2015-10-16 8:03 ` Marc Zyngier
0 siblings, 1 reply; 30+ messages in thread
From: Arnd Bergmann @ 2015-10-15 19:16 UTC (permalink / raw)
To: Marc Zyngier
Cc: linux-arm-kernel, Thomas Gleixner, Jiang Liu, Jason Cooper,
linux-pci, linux-kernel, Ma Jun
On Thursday 15 October 2015 17:01:02 Marc Zyngier wrote:
>
> "Preconfigured" is the key word. While you can do something like that if
> your hardware treats MSIs just as if they were wired interrupts
> (something like GICv2m), it becomes far more hairy if the target of MSIs
> is something like a GICv3 ITS (which is the case for HiSilicon mbigen).
>
> The main reason is that the ITS relies on "translation tables" kept in
> memory, which the OS has to configure, and handing over pre-configured
> tables is not something I'm looking forward to doing. From a CPU point
> of view, this is akin entering the kernel with the MMU already on and no
> idmap...
>
> The approach taken here is to make the MSI-ness explicit at the irqchip
> level, and keep the interrupting device oblivious of that feature. Also,
> this relies on the fact that we can have one MSI per wire, meaning that
> we don't have to multiplex anything (no nested irqchip), and that we can
> rely on hierarchical domains, which simplifies the code (at least for
> the irqchip).
>
Thanks, that already makes things much clearer. Just one more question:
why can't those translation tables be configured statically by the
irqchip driver? Is this all about being able to cut a few cycles
in case of virtualization? I would assume that once you have gone through
the overhead of having both an MSI and a normal interrupt line (with
the need for serialization vs DMA), you can just as well trap to user
space to deliver an IRQ to a guest.
Arnd
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH RFC 0/7] Adding core support for wire-MSI bridges
2015-10-15 19:16 ` Arnd Bergmann
@ 2015-10-16 8:03 ` Marc Zyngier
2015-10-16 8:45 ` Arnd Bergmann
0 siblings, 1 reply; 30+ messages in thread
From: Marc Zyngier @ 2015-10-16 8:03 UTC (permalink / raw)
To: Arnd Bergmann
Cc: linux-arm-kernel, Thomas Gleixner, Jiang Liu, Jason Cooper,
linux-pci, linux-kernel, Ma Jun
On 15/10/15 20:16, Arnd Bergmann wrote:
> On Thursday 15 October 2015 17:01:02 Marc Zyngier wrote:
>>
>> "Preconfigured" is the key word. While you can do something like that if
>> your hardware treats MSIs just as if they were wired interrupts
>> (something like GICv2m), it becomes far more hairy if the target of MSIs
>> is something like a GICv3 ITS (which is the case for HiSilicon mbigen).
>>
>> The main reason is that the ITS relies on "translation tables" kept in
>> memory, which the OS has to configure, and handing over pre-configured
>> tables is not something I'm looking forward to doing. From a CPU point
>> of view, this is akin entering the kernel with the MMU already on and no
>> idmap...
>>
>> The approach taken here is to make the MSI-ness explicit at the irqchip
>> level, and keep the interrupting device oblivious of that feature. Also,
>> this relies on the fact that we can have one MSI per wire, meaning that
>> we don't have to multiplex anything (no nested irqchip), and that we can
>> rely on hierarchical domains, which simplifies the code (at least for
>> the irqchip).
>>
>
> Thanks, that already makes things much clearer. Just one more question:
> why can't those translation tables be configured statically by the
> irqchip driver? Is this all about being able to cut a few cycles
> in case of virtualization?
Having a static configuration, while doable, complicates things for
everybody else. The LPI number used by the irqchip would need to be put
an some "exclusion list" to make sure it is not reallocated for other
subsystems (e.g PCI). The translation tables also define the target CPU,
which could cause interesting problems once combined with CPU hotplug if
the ITS is not completely in control of it.
I'm not really getting your point about virtualization though.
> I would assume that once you have gone through the overhead of having
> both an MSI and a normal interrupt line (with the need for
> serialization vs DMA), you can just as well trap to user space to
> deliver an IRQ to a guest.
The whole idea behind this bridge is to move wired interrupts to the
periphery of a SoC. I don't think virtualization was part of the
equation, but of course I can't speak for the "geniuses" behind the idea.
Or maybe I'm reading your question the wrong way, which is entirely
possible given the lack of caffeine.
Thanks,
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH RFC 0/7] Adding core support for wire-MSI bridges
2015-10-16 8:03 ` Marc Zyngier
@ 2015-10-16 8:45 ` Arnd Bergmann
0 siblings, 0 replies; 30+ messages in thread
From: Arnd Bergmann @ 2015-10-16 8:45 UTC (permalink / raw)
To: Marc Zyngier
Cc: linux-arm-kernel, Thomas Gleixner, Jiang Liu, Jason Cooper,
linux-pci, linux-kernel, Ma Jun
On Friday 16 October 2015 09:03:14 Marc Zyngier wrote:
> On 15/10/15 20:16, Arnd Bergmann wrote:
> > On Thursday 15 October 2015 17:01:02 Marc Zyngier wrote:
> >>
> >> "Preconfigured" is the key word. While you can do something like that if
> >> your hardware treats MSIs just as if they were wired interrupts
> >> (something like GICv2m), it becomes far more hairy if the target of MSIs
> >> is something like a GICv3 ITS (which is the case for HiSilicon mbigen).
> >>
> >> The main reason is that the ITS relies on "translation tables" kept in
> >> memory, which the OS has to configure, and handing over pre-configured
> >> tables is not something I'm looking forward to doing. From a CPU point
> >> of view, this is akin entering the kernel with the MMU already on and no
> >> idmap...
> >>
> >> The approach taken here is to make the MSI-ness explicit at the irqchip
> >> level, and keep the interrupting device oblivious of that feature. Also,
> >> this relies on the fact that we can have one MSI per wire, meaning that
> >> we don't have to multiplex anything (no nested irqchip), and that we can
> >> rely on hierarchical domains, which simplifies the code (at least for
> >> the irqchip).
> >>
> >
> > Thanks, that already makes things much clearer. Just one more question:
> > why can't those translation tables be configured statically by the
> > irqchip driver? Is this all about being able to cut a few cycles
> > in case of virtualization?
>
> Having a static configuration, while doable, complicates things for
> everybody else. The LPI number used by the irqchip would need to be put
> an some "exclusion list" to make sure it is not reallocated for other
> subsystems (e.g PCI). The translation tables also define the target CPU,
> which could cause interesting problems once combined with CPU hotplug if
> the ITS is not completely in control of it.
>
> I'm not really getting your point about virtualization though.
I think I'm mainly still confused by how MSI is implemented on
the CPU side. Your explanation makes sense though.
> > I would assume that once you have gone through the overhead of having
> > both an MSI and a normal interrupt line (with the need for
> > serialization vs DMA), you can just as well trap to user space to
> > deliver an IRQ to a guest.
>
> The whole idea behind this bridge is to move wired interrupts to the
> periphery of a SoC. I don't think virtualization was part of the
> equation, but of course I can't speak for the "geniuses" behind the idea.
>
> Or maybe I'm reading your question the wrong way, which is entirely
> possible given the lack of caffeine.
No, I think I get it now.
Arnd
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH RFC 0/7] Adding core support for wire-MSI bridges
2015-10-15 15:39 [PATCH RFC 0/7] Adding core support for wire-MSI bridges Marc Zyngier
` (7 preceding siblings ...)
2015-10-15 15:46 ` [PATCH RFC 0/7] Adding core support for wire-MSI bridges Arnd Bergmann
@ 2015-10-16 1:55 ` Jiang Liu
2015-10-16 8:48 ` Marc Zyngier
8 siblings, 1 reply; 30+ messages in thread
From: Jiang Liu @ 2015-10-16 1:55 UTC (permalink / raw)
To: Marc Zyngier, Thomas Gleixner, Jason Cooper
Cc: Ma Jun, linux-arm-kernel, linux-pci, linux-kernel
On 2015/10/15 23:39, Marc Zyngier wrote:
> There seems to be a new class of interrupt controller out there whose
> sole purpose (apart from making everybody's life a nightmare) is to
> turn wired interrupts into MSIs.
>
> Instead of considering that the MSIs allocated to a device are for the
> direct use of that device, we can turn this set of MSIs into a irq
> domain, and use that domain to build a standard irqchip on top of
> that.
Hi Marc,
There's a working to enable Intel VMD storage device, which
has the similar requirement. Basically a PCIe hierarchy is hidden
behind a parent PCIe device, so we need to use the PCIe irqs on parent
to de-multiple PCIe IRQs from hidden PCIe devices. Seems a chance for
consolidation here.
cc Keith Busch <keith.busch@intel.com> who is the author of
VMD device driver.
Thanks!
Gerry
>
> This requires some (slightly ugly) surgery in both the generic MSI and
> platform MSI layers, but the amount of code is actually relatively
> small (about +150 LoC so far).
>
> On top of that, we add a dummy driver for a such a bridge, hoping that
> this will give enough information to driver authors so that they can
> use this new feature. An even more stupid client driver is provided to
> show the interrupt stack allocation:
>
> dummydev dummy-dev: Probing
> dummydev dummy-dev: Allocated IRQ35
> dummydev dummy-dev: Probing OK
> dummydev dummy-dev: IRQ35 hwirq 5 domain msichip_domain_ops
> dummydev dummy-dev: IRQ35 hwirq 0 domain msi_domain_ops
> dummydev dummy-dev: IRQ35 hwirq 8192 domain its_domain_ops
> dummydev dummy-dev: IRQ35 hwirq 8192 domain gic_irq_domain_ops
>
> While this seems to work, it is far from being perfect:
>
> - This is a prototype: error handling is rubbish, and there could be
> better abstractions to use.
>
> - It relies on not declaring this bridge with IRQCHIP_DECLARE in order
> to prevent the DT layer from allocating interrupts behind our back.
>
> - There is some probe ordering issues between the bridge and the wired
> interrupt device, leading to the use of -EPROBE_DEFER.
>
> The last two points could be addressed directly in the OF layer, as
> this is a generic device ordering issue (and people are already
> working on that).
>
> I'd welcome any comment on that approach (though I'm going to make
> myself scarse over the next two weeks).
>
> Marc Zyngier (7):
> platform-msi: Allow MSIs to be allocated in chunks
> platform-msi: Factor out allocation/free of private data
> irqdomain: Make irq_domain_alloc_irqs_recursive available
> genirq/msi: Make the .prepare callback reusable
> genirq/msi: Add msi_domain_populate_irqs
> platform-msi: Allow creation of a MSI-based stacked irq domain
> irqchip: [Example] dummy wired interrupt/MSI bridge driver
>
> drivers/base/platform-msi.c | 185 ++++++++++++++++++++--------
> drivers/irqchip/Kconfig | 7 ++
> drivers/irqchip/Makefile | 1 +
> drivers/irqchip/irq-msichip.c | 271 ++++++++++++++++++++++++++++++++++++++++++
> include/linux/irqdomain.h | 3 +
> include/linux/msi.h | 16 +++
> kernel/irq/irqdomain.c | 6 +-
> kernel/irq/msi.c | 47 +++++++-
> 8 files changed, 481 insertions(+), 55 deletions(-)
> create mode 100644 drivers/irqchip/irq-msichip.c
>
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH RFC 0/7] Adding core support for wire-MSI bridges
2015-10-16 1:55 ` Jiang Liu
@ 2015-10-16 8:48 ` Marc Zyngier
2015-11-04 13:34 ` Thomas Gleixner
0 siblings, 1 reply; 30+ messages in thread
From: Marc Zyngier @ 2015-10-16 8:48 UTC (permalink / raw)
To: Jiang Liu, Thomas Gleixner, Jason Cooper
Cc: Ma Jun, linux-arm-kernel, linux-pci, linux-kernel
Hi Gerry,
On 16/10/15 02:55, Jiang Liu wrote:
> On 2015/10/15 23:39, Marc Zyngier wrote:
>> There seems to be a new class of interrupt controller out there whose
>> sole purpose (apart from making everybody's life a nightmare) is to
>> turn wired interrupts into MSIs.
>>
>> Instead of considering that the MSIs allocated to a device are for the
>> direct use of that device, we can turn this set of MSIs into a irq
>> domain, and use that domain to build a standard irqchip on top of
>> that.
> Hi Marc,
> There's a working to enable Intel VMD storage device, which
> has the similar requirement. Basically a PCIe hierarchy is hidden
> behind a parent PCIe device, so we need to use the PCIe irqs on parent
> to de-multiple PCIe IRQs from hidden PCIe devices. Seems a chance for
> consolidation here.
Do you know if there is a 1-1 mapping between the interrupts seen by the
parent device and those seen by the hidden devices? Or is it a case of
having to demultiplex the MSIs? Looks like the former, but I'd like to
be sure.
I just had a quick look at the code there:
https://lkml.org/lkml/2015/8/27/674
Is there anything more recent?
> cc Keith Busch <keith.busch@intel.com> who is the author of
> VMD device driver.
Sure, will do when I repost this (probably in a few weeks), and assuming
this fits the bill for Thomas and the MBIGEN folks.
Thanks,
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH RFC 0/7] Adding core support for wire-MSI bridges
2015-10-16 8:48 ` Marc Zyngier
@ 2015-11-04 13:34 ` Thomas Gleixner
2015-11-05 12:22 ` Marc Zyngier
0 siblings, 1 reply; 30+ messages in thread
From: Thomas Gleixner @ 2015-11-04 13:34 UTC (permalink / raw)
To: Marc Zyngier
Cc: Jiang Liu, Jason Cooper, Ma Jun, linux-arm-kernel, linux-pci,
linux-kernel
Marc,
On Fri, 16 Oct 2015, Marc Zyngier wrote:
> On 16/10/15 02:55, Jiang Liu wrote:
> > There's a working to enable Intel VMD storage device, which
> > has the similar requirement. Basically a PCIe hierarchy is hidden
> > behind a parent PCIe device, so we need to use the PCIe irqs on parent
> > to de-multiple PCIe IRQs from hidden PCIe devices. Seems a chance for
> > consolidation here.
>
> Do you know if there is a 1-1 mapping between the interrupts seen by the
> parent device and those seen by the hidden devices? Or is it a case of
> having to demultiplex the MSIs? Looks like the former, but I'd like to
> be sure.
Yes, it's a demultiplexer. No 1:1 mapping.
> Sure, will do when I repost this (probably in a few weeks), and assuming
> this fits the bill for Thomas and the MBIGEN folks.
It doesn't look that bad and the resulting mbigen stuff is way less
horrible than it was before. So I agree this is a possible solution to
the problem.
Thanks,
tglx
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH RFC 0/7] Adding core support for wire-MSI bridges
2015-11-04 13:34 ` Thomas Gleixner
@ 2015-11-05 12:22 ` Marc Zyngier
2015-11-05 12:25 ` Thomas Gleixner
0 siblings, 1 reply; 30+ messages in thread
From: Marc Zyngier @ 2015-11-05 12:22 UTC (permalink / raw)
To: Thomas Gleixner
Cc: Jiang Liu, Jason Cooper, Ma Jun, linux-arm-kernel, linux-pci,
linux-kernel
On 04/11/15 13:34, Thomas Gleixner wrote:
> Marc,
>
> On Fri, 16 Oct 2015, Marc Zyngier wrote:
>> On 16/10/15 02:55, Jiang Liu wrote:
>>> There's a working to enable Intel VMD storage device, which
>>> has the similar requirement. Basically a PCIe hierarchy is hidden
>>> behind a parent PCIe device, so we need to use the PCIe irqs on parent
>>> to de-multiple PCIe IRQs from hidden PCIe devices. Seems a chance for
>>> consolidation here.
>>
>> Do you know if there is a 1-1 mapping between the interrupts seen by the
>> parent device and those seen by the hidden devices? Or is it a case of
>> having to demultiplex the MSIs? Looks like the former, but I'd like to
>> be sure.
>
> Yes, it's a demultiplexer. No 1:1 mapping.
Right. This doesn't exactly fit the scheme I have so far (there is a 1:1
mapping between the wired interrupt and the MSI), but once we are able
to expose an MSI domain, it could be possible to construct the MSI
demultiplexer on top. That's a lot of layers! ;-)
>> Sure, will do when I repost this (probably in a few weeks), and assuming
>> this fits the bill for Thomas and the MBIGEN folks.
>
> It doesn't look that bad and the resulting mbigen stuff is way less
> horrible than it was before. So I agree this is a possible solution to
> the problem.
Cool. I'll revisit that after the merge window.
Thanks,
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH RFC 0/7] Adding core support for wire-MSI bridges
2015-11-05 12:22 ` Marc Zyngier
@ 2015-11-05 12:25 ` Thomas Gleixner
0 siblings, 0 replies; 30+ messages in thread
From: Thomas Gleixner @ 2015-11-05 12:25 UTC (permalink / raw)
To: Marc Zyngier
Cc: Jiang Liu, Jason Cooper, Ma Jun, linux-arm-kernel, linux-pci,
linux-kernel
On Thu, 5 Nov 2015, Marc Zyngier wrote:
> On 04/11/15 13:34, Thomas Gleixner wrote:
> > Marc,
> >
> > On Fri, 16 Oct 2015, Marc Zyngier wrote:
> >> On 16/10/15 02:55, Jiang Liu wrote:
> >>> There's a working to enable Intel VMD storage device, which
> >>> has the similar requirement. Basically a PCIe hierarchy is hidden
> >>> behind a parent PCIe device, so we need to use the PCIe irqs on parent
> >>> to de-multiple PCIe IRQs from hidden PCIe devices. Seems a chance for
> >>> consolidation here.
> >>
> >> Do you know if there is a 1-1 mapping between the interrupts seen by the
> >> parent device and those seen by the hidden devices? Or is it a case of
> >> having to demultiplex the MSIs? Looks like the former, but I'd like to
> >> be sure.
> >
> > Yes, it's a demultiplexer. No 1:1 mapping.
>
> Right. This doesn't exactly fit the scheme I have so far (there is a 1:1
> mapping between the wired interrupt and the MSI), but once we are able
> to expose an MSI domain, it could be possible to construct the MSI
> demultiplexer on top. That's a lot of layers! ;-)
Well for the demux case it doesn't make a lot of sense. It's not easy
to describe in a hierarchy. Having that parentless MSI domain for that
VMD case is simple enough.
Thanks,
tglx
^ permalink raw reply [flat|nested] 30+ messages in thread