linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] irqchip: gicv3-its: Fixes for 3.19-rc1
@ 2014-12-12 10:51 Marc Zyngier
  2014-12-12 10:51 ` [PATCH 1/3] irqchip: gicv3-its: Fix domain free in multi-MSI case Marc Zyngier
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Marc Zyngier @ 2014-12-12 10:51 UTC (permalink / raw)
  To: linux-arm-kernel

This small series contains a number of moderately important fixes for
the GICv3 ITS:

- proper deallocation of LPIs for multi-MSI
- cleaner separation of resource alloc/free vs HW configuration
- fix the allocation of Interrupt Translation Tables

This should be applied on top of the ITS code, currently scheduled to
go in -rc1.

Marc Zyngier (3):
  irqchip: gicv3-its: Fix domain free in multi-MSI case
  irqchip: gicv3-its: Move some alloc/free code to activate/deactivate
  irqchip: gicv3-its: Fix ITT allocation

 drivers/irqchip/irq-gic-v3-its.c | 45 ++++++++++++++++++++++++++++++----------
 1 file changed, 34 insertions(+), 11 deletions(-)

-- 
2.1.3

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/3] irqchip: gicv3-its: Fix domain free in multi-MSI case
  2014-12-12 10:51 [PATCH 0/3] irqchip: gicv3-its: Fixes for 3.19-rc1 Marc Zyngier
@ 2014-12-12 10:51 ` Marc Zyngier
  2014-12-12 10:51 ` [PATCH 2/3] irqchip: gicv3-its: Move some alloc/free code to activate/deactivate Marc Zyngier
  2014-12-12 10:51 ` [PATCH 3/3] irqchip: gicv3-its: Fix ITT allocation Marc Zyngier
  2 siblings, 0 replies; 4+ messages in thread
From: Marc Zyngier @ 2014-12-12 10:51 UTC (permalink / raw)
  To: linux-arm-kernel

Fix stupid thinko on the path freeing the interrupts, where only
the first interrupt would get reset, and none of the others.

This should only affect multi-MSI allocations.

Reported-by: Wuyun Wu (Abel) <wuyun.wu@huawei.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/irqchip/irq-gic-v3-its.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index e9d1615..ab01852 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -1210,7 +1210,7 @@ static void its_irq_domain_free(struct irq_domain *domain, unsigned int virq,
 		clear_bit(event, its_dev->lpi_map);
 
 		/* Nuke the entry in the domain */
-		irq_domain_reset_irq_data(d);
+		irq_domain_reset_irq_data(data);
 	}
 
 	/* If all interrupts have been freed, start mopping the floor */
-- 
2.1.3

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/3] irqchip: gicv3-its: Move some alloc/free code to activate/deactivate
  2014-12-12 10:51 [PATCH 0/3] irqchip: gicv3-its: Fixes for 3.19-rc1 Marc Zyngier
  2014-12-12 10:51 ` [PATCH 1/3] irqchip: gicv3-its: Fix domain free in multi-MSI case Marc Zyngier
@ 2014-12-12 10:51 ` Marc Zyngier
  2014-12-12 10:51 ` [PATCH 3/3] irqchip: gicv3-its: Fix ITT allocation Marc Zyngier
  2 siblings, 0 replies; 4+ messages in thread
From: Marc Zyngier @ 2014-12-12 10:51 UTC (permalink / raw)
  To: linux-arm-kernel

The ITS code could do a bit less in the alloc/free paths, and a bit
more in the activate/deactivate methods, giving a better separation
between software allocation and HW programing.

Suggested-by: Wuyun Wu (Abel) <wuyun.wu@huawei.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/irqchip/irq-gic-v3-its.c | 30 +++++++++++++++++++++++-------
 1 file changed, 23 insertions(+), 7 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index ab01852..98144fd 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -1102,9 +1102,6 @@ static int its_alloc_device_irq(struct its_device *dev, irq_hw_number_t *hwirq)
 	*hwirq = dev->lpi_base + idx;
 	set_bit(idx, dev->lpi_map);
 
-	/* Map the GIC irq ID to the device */
-	its_send_mapvi(dev, *hwirq, idx);
-
 	return 0;
 }
 
@@ -1191,6 +1188,26 @@ static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
 	return 0;
 }
 
+static void its_irq_domain_activate(struct irq_domain *domain,
+				    struct irq_data *d)
+{
+	struct its_device *its_dev = irq_data_get_irq_chip_data(d);
+	u32 event = its_get_event_id(d);
+
+	/* Map the GIC IRQ and event to the device */
+	its_send_mapvi(its_dev, d->hwirq, event);
+}
+
+static void its_irq_domain_deactivate(struct irq_domain *domain,
+				      struct irq_data *d)
+{
+	struct its_device *its_dev = irq_data_get_irq_chip_data(d);
+	u32 event = its_get_event_id(d);
+
+	/* Stop the delivery of interrupts */
+	its_send_discard(its_dev, event);
+}
+
 static void its_irq_domain_free(struct irq_domain *domain, unsigned int virq,
 				unsigned int nr_irqs)
 {
@@ -1201,10 +1218,7 @@ static void its_irq_domain_free(struct irq_domain *domain, unsigned int virq,
 	for (i = 0; i < nr_irqs; i++) {
 		struct irq_data *data = irq_domain_get_irq_data(domain,
 								virq + i);
-		int event = its_get_event_id(data);
-
-		/* Stop the delivery of interrupts */
-		its_send_discard(its_dev, event);
+		u32 event = its_get_event_id(data);
 
 		/* Mark interrupt index as unused */
 		clear_bit(event, its_dev->lpi_map);
@@ -1230,6 +1244,8 @@ static void its_irq_domain_free(struct irq_domain *domain, unsigned int virq,
 static const struct irq_domain_ops its_domain_ops = {
 	.alloc			= its_irq_domain_alloc,
 	.free			= its_irq_domain_free,
+	.activate		= its_irq_domain_activate,
+	.deactivate		= its_irq_domain_deactivate,
 };
 
 static int its_probe(struct device_node *node, struct irq_domain *parent)
-- 
2.1.3

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 3/3] irqchip: gicv3-its: Fix ITT allocation
  2014-12-12 10:51 [PATCH 0/3] irqchip: gicv3-its: Fixes for 3.19-rc1 Marc Zyngier
  2014-12-12 10:51 ` [PATCH 1/3] irqchip: gicv3-its: Fix domain free in multi-MSI case Marc Zyngier
  2014-12-12 10:51 ` [PATCH 2/3] irqchip: gicv3-its: Move some alloc/free code to activate/deactivate Marc Zyngier
@ 2014-12-12 10:51 ` Marc Zyngier
  2 siblings, 0 replies; 4+ messages in thread
From: Marc Zyngier @ 2014-12-12 10:51 UTC (permalink / raw)
  To: linux-arm-kernel

When issuing a MAPD command, one of the parameters passed to the ITS
is the number of EventID bits used to index the per-device Interrupt
Translation Table (ITT). Crucially, this is the number of bits
*minus one*.

This has two consequences:
- The size of the ITT has to be a strict power of two, no matter
  how many different events the device is actually going to generate.
- It is impossible to express an ITT with a single entry, as you
  would have to tell the ITS to "use zero bit from the EventID",
  and that clashes with "minus one" above.

Fix this by allocating the ITT with the number of vectors rounded up
to the next power of two, with a minimum of two entries.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 drivers/irqchip/irq-gic-v3-its.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 98144fd..86e4684 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -228,7 +228,7 @@ static struct its_collection *its_build_mapd_cmd(struct its_cmd_block *cmd,
 						 struct its_cmd_desc *desc)
 {
 	unsigned long itt_addr;
-	u8 size = order_base_2(desc->its_mapd_cmd.dev->nr_ites);
+	u8 size = ilog2(desc->its_mapd_cmd.dev->nr_ites);
 
 	itt_addr = virt_to_phys(desc->its_mapd_cmd.dev->itt);
 	itt_addr = ALIGN(itt_addr, ITS_ITT_ALIGN);
@@ -1043,11 +1043,18 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
 	void *itt;
 	int lpi_base;
 	int nr_lpis;
+	int nr_ites;
 	int cpu;
 	int sz;
 
 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-	sz = nvecs * its->ite_size;
+	/*
+	 * At least one bit of EventID is being used, hence a minimum
+	 * of two entries. No, the architecture doesn't let you
+	 * express an ITT with a single entry.
+	 */
+	nr_ites = max(2, roundup_pow_of_two(nvecs));
+	sz = nr_ites * its->ite_size;
 	sz = max(sz, ITS_ITT_ALIGN) + ITS_ITT_ALIGN - 1;
 	itt = kmalloc(sz, GFP_KERNEL);
 	lpi_map = its_lpi_alloc_chunks(nvecs, &lpi_base, &nr_lpis);
@@ -1061,7 +1068,7 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
 
 	dev->its = its;
 	dev->itt = itt;
-	dev->nr_ites = nvecs;
+	dev->nr_ites = nr_ites;
 	dev->lpi_map = lpi_map;
 	dev->lpi_base = lpi_base;
 	dev->nr_lpis = nr_lpis;
-- 
2.1.3

^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2014-12-12 10:51 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-12-12 10:51 [PATCH 0/3] irqchip: gicv3-its: Fixes for 3.19-rc1 Marc Zyngier
2014-12-12 10:51 ` [PATCH 1/3] irqchip: gicv3-its: Fix domain free in multi-MSI case Marc Zyngier
2014-12-12 10:51 ` [PATCH 2/3] irqchip: gicv3-its: Move some alloc/free code to activate/deactivate Marc Zyngier
2014-12-12 10:51 ` [PATCH 3/3] irqchip: gicv3-its: Fix ITT allocation Marc Zyngier

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).