From 778031ccb58be6dccfb46314965bc8ff52c55f3d Mon Sep 17 00:00:00 2001 From: Runmin Wang Date: Mon, 23 Jan 2017 12:30:07 -0800 Subject: [PATCH] genirq: Add IRQ_AFFINITY_MANAGED flag Add IRQ_AFFINITY_MANAGED flag and related kernel APIs so that kernel driver can modify an irq's status in such a way that user space affinity change will be ignored. Kernel space's affinity setting will not be changed. Change-Id: Ib2d5ea651263bff4317562af69079ad950c9e71e Signed-off-by: Runmin Wang --- include/linux/irq.h | 4 +++- kernel/irq/chip.c | 5 ++++- kernel/irq/settings.h | 12 ++++++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/include/linux/irq.h b/include/linux/irq.h index de7f8d306feb..b0bcc1561d3d 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -73,6 +73,7 @@ enum irqchip_irq_state; * it from the spurious interrupt detection * mechanism and from core side polling. * IRQ_DISABLE_UNLAZY - Disable lazy irq disable + * IRQ_AFFINITY_MANAGED - Affinity is auto-managed by the kernel */ enum { IRQ_TYPE_NONE = 0x00000000, @@ -99,13 +100,14 @@ enum { IRQ_PER_CPU_DEVID = (1 << 17), IRQ_IS_POLLED = (1 << 18), IRQ_DISABLE_UNLAZY = (1 << 19), + IRQ_AFFINITY_MANAGED = (1 << 21), }; #define IRQF_MODIFY_MASK \ (IRQ_TYPE_SENSE_MASK | IRQ_NOPROBE | IRQ_NOREQUEST | \ IRQ_NOAUTOEN | IRQ_MOVE_PCNTXT | IRQ_LEVEL | IRQ_NO_BALANCING | \ IRQ_PER_CPU | IRQ_NESTED_THREAD | IRQ_NOTHREAD | IRQ_PER_CPU_DEVID | \ - IRQ_IS_POLLED | IRQ_DISABLE_UNLAZY) + IRQ_IS_POLLED | IRQ_DISABLE_UNLAZY | IRQ_AFFINITY_MANAGED) #define IRQ_NO_BALANCING_MASK (IRQ_PER_CPU | IRQ_NO_BALANCING) diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index 15206453b12a..9812d9c0d483 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c @@ -836,7 +836,8 @@ void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set) irq_settings_clr_and_set(desc, clr, set); irqd_clear(&desc->irq_data, IRQD_NO_BALANCING | IRQD_PER_CPU | - IRQD_TRIGGER_MASK | IRQD_LEVEL | IRQD_MOVE_PCNTXT); + IRQD_TRIGGER_MASK | IRQD_LEVEL | IRQD_MOVE_PCNTXT | + IRQD_AFFINITY_MANAGED); if (irq_settings_has_no_balance_set(desc)) irqd_set(&desc->irq_data, IRQD_NO_BALANCING); if (irq_settings_is_per_cpu(desc)) @@ -845,6 +846,8 @@ void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set) irqd_set(&desc->irq_data, IRQD_MOVE_PCNTXT); if (irq_settings_is_level(desc)) irqd_set(&desc->irq_data, IRQD_LEVEL); + if (irq_settings_has_affinity_managed_set(desc)) + irqd_set(&desc->irq_data, IRQD_AFFINITY_MANAGED); irqd_set(&desc->irq_data, irq_settings_get_trigger_mask(desc)); diff --git a/kernel/irq/settings.h b/kernel/irq/settings.h index 320579d89091..f0964f058521 100644 --- a/kernel/irq/settings.h +++ b/kernel/irq/settings.h @@ -17,6 +17,7 @@ enum { _IRQ_IS_POLLED = IRQ_IS_POLLED, _IRQ_DISABLE_UNLAZY = IRQ_DISABLE_UNLAZY, _IRQF_MODIFY_MASK = IRQF_MODIFY_MASK, + _IRQ_AFFINITY_MANAGED = IRQ_AFFINITY_MANAGED, }; #define IRQ_PER_CPU GOT_YOU_MORON @@ -32,6 +33,7 @@ enum { #define IRQ_DISABLE_UNLAZY GOT_YOU_MORON #undef IRQF_MODIFY_MASK #define IRQF_MODIFY_MASK GOT_YOU_MORON +#define IRQ_AFFINITY_MANAGED GOT_YOU_MORON static inline void irq_settings_clr_and_set(struct irq_desc *desc, u32 clr, u32 set) @@ -65,6 +67,16 @@ static inline bool irq_settings_has_no_balance_set(struct irq_desc *desc) return desc->status_use_accessors & _IRQ_NO_BALANCING; } +static inline void irq_settings_set_affinity_managed(struct irq_desc *desc) +{ + desc->status_use_accessors |= _IRQ_AFFINITY_MANAGED; +} + +static inline bool irq_settings_has_affinity_managed_set(struct irq_desc *desc) +{ + return desc->status_use_accessors & _IRQ_AFFINITY_MANAGED; +} + static inline u32 irq_settings_get_trigger_mask(struct irq_desc *desc) { return desc->status_use_accessors & IRQ_TYPE_SENSE_MASK;