2015-09-24 12:32:13 +03:00
/*
* 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 ) ;
const struct cpumask * affinity = d - > common - > affinity ;
struct irq_chip * c ;
bool ret = false ;
/*
* If this is a per - CPU interrupt , or the affinity does not
* include this CPU , then we have nothing to do .
*/
if ( irqd_is_per_cpu ( d ) | |
! cpumask_test_cpu ( smp_processor_id ( ) , affinity ) )
return false ;
if ( cpumask_any_and ( affinity , cpu_online_mask ) > = nr_cpu_ids ) {
affinity = cpu_online_mask ;
ret = true ;
}
c = irq_data_get_irq_chip ( d ) ;
if ( ! c - > irq_set_affinity ) {
2015-10-22 15:34:57 +03:00
pr_debug ( " IRQ%u: unable to set affinity \n " , d - > irq ) ;
2015-09-24 12:32:13 +03:00
} else {
int r = irq_do_set_affinity ( d , affinity , false ) ;
if ( r )
pr_warn_ratelimited ( " IRQ%u: set affinity failed(%d). \n " ,
d - > irq , r ) ;
}
return ret ;
}
/**
* 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 )
{
unsigned int irq ;
struct irq_desc * desc ;
unsigned long flags ;
local_irq_save ( flags ) ;
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 ( ) ) ;
}
local_irq_restore ( flags ) ;
}