linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
From: jonathan.austin@arm.com (Jonathan Austin)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 02/13] ARM: gic: add CPU migration support
Date: Thu, 25 Jul 2013 12:44:05 +0100	[thread overview]
Message-ID: <51F10F85.7090508@arm.com> (raw)
In-Reply-To: <1374550289-25305-3-git-send-email-nicolas.pitre@linaro.org>

Hi Nico,

I've got a couple of minor questions/comments about this one...

On 23/07/13 04:31, Nicolas Pitre wrote:
> This is required by the big.LITTLE switcher code.
>
> The gic_migrate_target() changes the CPU interface mapping for the
> current CPU to redirect SGIs to the specified interface, and it also
> updates the target CPU for each interrupts to that CPU interface
> if they were targeting the current interface.  Finally, pending
> SGIs for the current CPU are forwarded to the new interface.
>
> Because Linux does not use it, the SGI source information for the
> forwarded SGIs is not preserved.  Neither is the source information
> for the SGIs sent by the current CPU to other CPUs adjusted to match
> the new CPU interface mapping.  The required registers are banked so
> only the target CPU could do it.
>
> Signed-off-by: Nicolas Pitre <nico@linaro.org>
> ---
>   drivers/irqchip/irq-gic.c       | 81 +++++++++++++++++++++++++++++++++++++++--
>   include/linux/irqchip/arm-gic.h |  4 ++
>   2 files changed, 82 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
> index ee7c503120..6bd5a8c1aa 100644
> --- a/drivers/irqchip/irq-gic.c
> +++ b/drivers/irqchip/irq-gic.c
> @@ -253,10 +253,9 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
>   	if (cpu >= NR_GIC_CPU_IF || cpu >= nr_cpu_ids)
>   		return -EINVAL;
>
> +	raw_spin_lock(&irq_controller_lock);
>   	mask = 0xff << shift;
>   	bit = gic_cpu_map[cpu] << shift;
> -
> -	raw_spin_lock(&irq_controller_lock);
>   	val = readl_relaxed(reg) & ~mask;
>   	writel_relaxed(val | bit, reg);
>   	raw_spin_unlock(&irq_controller_lock);
> @@ -646,7 +645,9 @@ static void __init gic_pm_init(struct gic_chip_data *gic)
>   void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
>   {
>   	int cpu;
> -	unsigned long map = 0;
> +	unsigned long flags, map = 0;
> +
> +	raw_spin_lock_irqsave(&irq_controller_lock, flags);
>
>   	/* Convert our logical CPU mask into a physical one. */
>   	for_each_cpu(cpu, mask)
> @@ -660,6 +661,80 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
>
>   	/* this always happens on GIC0 */
>   	writel_relaxed(map << 16 | irq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
> +
> +	raw_spin_unlock_irqrestore(&irq_controller_lock, flags);
> +}
> +#endif
> +
> +#ifdef CONFIG_BL_SWITCHER
> +/*
> + * gic_migrate_target - migrate IRQs to another PU interface

(nit) Should that be _C_PU?

> + *
> + * @new_cpu_id: the CPU target ID to migrate IRQs to
> + *
> + * Migrate all peripheral interrupts with a target matching the current CPU
> + * to the interface corresponding to @new_cpu_id.  The CPU interface mapping
> + * is also updated.  Targets to other CPU interfaces are unchanged.
> + * This must be called with IRQs locally disabled.
> + */
> +void gic_migrate_target(unsigned int new_cpu_id)
> +{
> +	unsigned int old_cpu_id, gic_irqs, gic_nr = 0;
> +	void __iomem *dist_base;
> +	int i, ror_val, cpu = smp_processor_id();
> +	u32 val, old_mask, active_mask;
> +
> +	if (gic_nr >= MAX_GIC_NR)
> +		BUG();
> +
> +	dist_base = gic_data_dist_base(&gic_data[gic_nr]);
> +	if (!dist_base)
> +		return;
> +	gic_irqs = gic_data[gic_nr].gic_irqs;
> +
> +	old_cpu_id = __ffs(gic_cpu_map[cpu]);
> +	old_mask = 0x01010101 << old_cpu_id;

I don't think this is very clear, though section 4.3.12 of the GIC spec 
helps a lot! A little pointer or some more self-evident name for the 
mask might be nice...

old_mask = GIC_ITARGETSR_MASK << old_cpu_id

or similar? This@least points one to the right bit of documentation?

> +	ror_val = (old_cpu_id - new_cpu_id) & 31;
> +
> +	raw_spin_lock(&irq_controller_lock);
> +
> +	gic_cpu_map[cpu] = 1 << new_cpu_id;
> +
> +	for (i = 8; i < DIV_ROUND_UP(gic_irqs, 4); i++) {

Does this '8' here warrant a #define? GIC_RO_INTR_REGS?

Perhaps everyone looking@the code will be familiar enough with the 
GIC to see immediately why the first 8 entries are being skipped...?

> +		val = readl_relaxed(dist_base + GIC_DIST_TARGET + i * 4);
> +		active_mask = val & old_mask;
> +		if (active_mask) {
> +			val &= ~active_mask;
> +			val |= ror32(active_mask, ror_val);
> +			writel_relaxed(val, dist_base + GIC_DIST_TARGET + i*4);
> +		}
> +	}
> +
> +	raw_spin_unlock(&irq_controller_lock);
> +
> +	/*
> +	 * Now let's migrate and clear any potential SGIs that might be
> +	 * pending for us (old_cpu_id).  Since GIC_DIST_SGI_PENDING_SET
> +	 * is a banked register, we can only forward the SGI using
> +	 * GIC_DIST_SOFTINT.  The original SGI source is lost but Linux
> +	 * doesn't use that information anyway.
> +	 *
> +	 * For the same reason we do not adjust SGI source information
> +	 * for previously sent SGIs by us to other CPUs either.
> +	 */
> +	for (i = 0; i < 16; i += 4) {
> +		int j;
> +		val = readl_relaxed(dist_base + GIC_DIST_SGI_PENDING_SET + i);
> +		if (!val)
> +			continue;
> +		writel_relaxed(val, dist_base + GIC_DIST_SGI_PENDING_CLEAR + i);
> +		for (j = i; j < i + 4; j++) {
> +			if (val & 0xff)
> +				writel_relaxed((1 << (new_cpu_id + 16)) | j,
> +						dist_base + GIC_DIST_SOFTINT);
> +			val >>= 8;
> +		}
> +	}

I'm curious as to why we don't need to do anything for PPIs here - could 
there be any pending PPIs that don't get handled (I guess retargetting 
doesn't make sense for these?)

>   }
>   #endif
>
> diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
> index 3e203eb23c..40bfcac959 100644
> --- a/include/linux/irqchip/arm-gic.h
> +++ b/include/linux/irqchip/arm-gic.h
> @@ -31,6 +31,8 @@
>   #define GIC_DIST_TARGET			0x800
>   #define GIC_DIST_CONFIG			0xc00
>   #define GIC_DIST_SOFTINT		0xf00
> +#define GIC_DIST_SGI_PENDING_CLEAR	0xf10
> +#define GIC_DIST_SGI_PENDING_SET	0xf20
>
>   #define GICH_HCR			0x0
>   #define GICH_VTR			0x4
> @@ -73,6 +75,8 @@ static inline void gic_init(unsigned int nr, int start,
>   	gic_init_bases(nr, start, dist, cpu, 0, NULL);
>   }
>
> +void gic_migrate_target(unsigned int new_cpu_id);
> +
>   #endif /* __ASSEMBLY */
>
>   #endif
>

  reply	other threads:[~2013-07-25 11:44 UTC|newest]

Thread overview: 43+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-07-23  3:31 [PATCH 00/13] The big.LITTLE In-Kernel Switcher (IKS), part 1 Nicolas Pitre
2013-07-23  3:31 ` [PATCH 01/13] ARM: suspend: use hash of cpu_logical_map value to index into save array Nicolas Pitre
2013-07-24 16:47   ` Dave Martin
2013-07-24 18:55     ` Nicolas Pitre
2013-07-25 10:55       ` Dave Martin
2013-07-25 16:06         ` Nicolas Pitre
2013-07-26 11:31           ` Lorenzo Pieralisi
2013-07-26 14:41             ` Nicolas Pitre
2013-07-26 15:34               ` Dave Martin
2013-07-26 15:43                 ` Nicolas Pitre
2013-07-26 15:45                   ` Dave Martin
2013-07-26 17:04                   ` Lorenzo Pieralisi
2013-07-26 19:19                     ` Nicolas Pitre
2013-07-29 11:50   ` Lorenzo Pieralisi
2013-07-30  2:08     ` Nicolas Pitre
2013-07-30  9:15       ` Dave Martin
2013-07-23  3:31 ` [PATCH 02/13] ARM: gic: add CPU migration support Nicolas Pitre
2013-07-25 11:44   ` Jonathan Austin [this message]
2013-07-25 19:11     ` Nicolas Pitre
2013-07-23  3:31 ` [PATCH 03/13] ARM: b.L: core switcher code Nicolas Pitre
2013-07-25 17:15   ` Jonathan Austin
2013-07-25 20:20     ` Nicolas Pitre
2013-07-26 10:45   ` Lorenzo Pieralisi
2013-07-26 14:29     ` Nicolas Pitre
2013-07-26 14:53   ` Russell King - ARM Linux
2013-07-26 15:10     ` Nicolas Pitre
2013-07-23  3:31 ` [PATCH 04/13] ARM: bL_switcher: add clockevent save/restore support Nicolas Pitre
2013-07-23  3:31 ` [PATCH 05/13] ARM: bL_switcher: move to dedicated threads rather than workqueues Nicolas Pitre
2013-07-26 15:18   ` Lorenzo Pieralisi
2013-07-26 15:39     ` Nicolas Pitre
2013-07-23  3:31 ` [PATCH 06/13] ARM: bL_switcher: simplify stack isolation Nicolas Pitre
2013-07-23  3:31 ` [PATCH 07/13] ARM: bL_switcher: hot-unplug half of the available CPUs Nicolas Pitre
2013-07-23  3:31 ` [PATCH 08/13] ARM: bL_switcher: do not hardcode GIC IDs in the code Nicolas Pitre
2013-07-23  3:31 ` [PATCH 09/13] ARM: bL_switcher: ability to enable and disable the switcher via sysfs Nicolas Pitre
2013-07-23  3:31 ` [PATCH 10/13] ARM: bL_switcher: add kernel cmdline param to disable the switcher on boot Nicolas Pitre
2013-07-23  3:31 ` [PATCH 11/13] ARM: bL_switcher: veto CPU hotplug requests when the switcher is active Nicolas Pitre
2013-07-31 10:30   ` Lorenzo Pieralisi
2013-08-05  4:25     ` Nicolas Pitre
2013-07-23  3:31 ` [PATCH 12/13] ARM: bL_switcher: remove assumptions between logical and physical CPUs Nicolas Pitre
2013-07-30 16:30   ` Lorenzo Pieralisi
2013-07-30 19:15     ` Nicolas Pitre
2013-07-31  9:41       ` Lorenzo Pieralisi
2013-07-23  3:31 ` [PATCH 13/13] ARM: bL_switcher: add a simple /dev user interface for debugging purposes Nicolas Pitre

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=51F10F85.7090508@arm.com \
    --to=jonathan.austin@arm.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is 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).