mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-10 15:58:47 +00:00
f0383c24b4
In order to move x86 to the generic hotplug migration code, add support for cleaning up move in progress bits. On architectures which have this x86 specific (mis)feature not enabled, this is optimized out by the compiler. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: Jens Axboe <axboe@kernel.dk> Cc: Marc Zyngier <marc.zyngier@arm.com> Cc: Michael Ellerman <mpe@ellerman.id.au> Cc: Keith Busch <keith.busch@intel.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Christoph Hellwig <hch@lst.de> Link: http://lkml.kernel.org/r/20170619235445.525817311@linutronix.de
115 lines
3.1 KiB
C
115 lines
3.1 KiB
C
/*
|
|
* Generic cpu hotunplug interrupt migration code copied from the
|
|
* arch/arm implementation
|
|
*
|
|
* Copyright (C) Russell King
|
|
*
|
|
* 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.
|
|
*/
|
|
#include <linux/interrupt.h>
|
|
#include <linux/ratelimit.h>
|
|
#include <linux/irq.h>
|
|
|
|
#include "internals.h"
|
|
|
|
static bool migrate_one_irq(struct irq_desc *desc)
|
|
{
|
|
struct irq_data *d = irq_desc_get_irq_data(desc);
|
|
struct irq_chip *chip = irq_data_get_irq_chip(d);
|
|
const struct cpumask *affinity;
|
|
bool brokeaff = false;
|
|
int err;
|
|
|
|
/*
|
|
* IRQ chip might be already torn down, but the irq descriptor is
|
|
* still in the radix tree. Also if the chip has no affinity setter,
|
|
* nothing can be done here.
|
|
*/
|
|
if (!chip || !chip->irq_set_affinity) {
|
|
pr_debug("IRQ %u: Unable to migrate away\n", d->irq);
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
* No move required, if:
|
|
* - Interrupt is per cpu
|
|
* - Interrupt is not started
|
|
* - Affinity mask does not include this CPU.
|
|
*
|
|
* Note: Do not check desc->action as this might be a chained
|
|
* interrupt.
|
|
*/
|
|
affinity = irq_data_get_affinity_mask(d);
|
|
if (irqd_is_per_cpu(d) || !irqd_is_started(d) ||
|
|
!cpumask_test_cpu(smp_processor_id(), affinity)) {
|
|
/*
|
|
* If an irq move is pending, abort it if the dying CPU is
|
|
* the sole target.
|
|
*/
|
|
irq_fixup_move_pending(desc, false);
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
* Complete an eventually pending irq move cleanup. If this
|
|
* interrupt was moved in hard irq context, then the vectors need
|
|
* to be cleaned up. It can't wait until this interrupt actually
|
|
* happens and this CPU was involved.
|
|
*/
|
|
irq_force_complete_move(desc);
|
|
|
|
/*
|
|
* If there is a setaffinity pending, then try to reuse the pending
|
|
* mask, so the last change of the affinity does not get lost. If
|
|
* there is no move pending or the pending mask does not contain
|
|
* any online CPU, use the current affinity mask.
|
|
*/
|
|
if (irq_fixup_move_pending(desc, true))
|
|
affinity = irq_desc_get_pending_mask(desc);
|
|
|
|
if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) {
|
|
affinity = cpu_online_mask;
|
|
brokeaff = true;
|
|
}
|
|
|
|
err = irq_do_set_affinity(d, affinity, false);
|
|
if (err) {
|
|
pr_warn_ratelimited("IRQ%u: set affinity failed(%d).\n",
|
|
d->irq, err);
|
|
return false;
|
|
}
|
|
return brokeaff;
|
|
}
|
|
|
|
/**
|
|
* irq_migrate_all_off_this_cpu - Migrate irqs away from offline cpu
|
|
*
|
|
* The current CPU has been marked offline. Migrate IRQs off this CPU.
|
|
* If the affinity settings do not allow other CPUs, force them onto any
|
|
* available CPU.
|
|
*
|
|
* Note: we must iterate over all IRQs, whether they have an attached
|
|
* action structure or not, as we need to get chained interrupts too.
|
|
*/
|
|
void irq_migrate_all_off_this_cpu(void)
|
|
{
|
|
struct irq_desc *desc;
|
|
unsigned int irq;
|
|
|
|
for_each_active_irq(irq) {
|
|
bool affinity_broken;
|
|
|
|
desc = irq_to_desc(irq);
|
|
raw_spin_lock(&desc->lock);
|
|
affinity_broken = migrate_one_irq(desc);
|
|
raw_spin_unlock(&desc->lock);
|
|
|
|
if (affinity_broken) {
|
|
pr_warn_ratelimited("IRQ %u: no longer affine to CPU%u\n",
|
|
irq, smp_processor_id());
|
|
}
|
|
}
|
|
}
|